Opentk/Source/Examples/Tutorial/T10_GLSL_Cube.cs

293 lines
11 KiB
C#

#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
#region --- Using Directives ---
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using OpenTK.OpenGL;
using OpenTK;
using System.Diagnostics;
using System.IO;
using OpenTK.OpenGL.Enums;
#endregion --- Using Directives ---
namespace Examples.Tutorial
{
/// <summary>
/// Demonstrates how to load and use a simple OpenGL shader program. Example is incomplete (documentation).
/// </summary>
public class T10_GLSL_Cube : GameWindow, IExample
{
#region --- Fields ---
static float angle = 0.0f, rotation_speed = 3.0f;
int vertex_shader_object, fragment_shader_object, shader_program;
int vertex_buffer_object, color_buffer_object, element_buffer_object;
Shapes.Shape shape = //new Examples.Shapes.Plane(8, 8, 4.0f, 4.0f);
new Examples.Shapes.Cube();
#endregion
#region --- Constructors ---
public T10_GLSL_Cube() : base(new DisplayMode(800, 600), "OpenTK | GLSL Example 1")
{
}
#endregion
#region OnLoad
/// <summary>
/// This is the place to load resources that change little
/// during the lifetime of the GameWindow. In this case, we
/// check for GLSL support, and load the shaders.
/// </summary>
/// <param name="e">Not used.</param>
public override void OnLoad(EventArgs e)
{
// Check for necessary capabilities:
if (!GL.SupportsExtension("VERSION_2_0"))
{
MessageBox.Show("You need at least OpenGL 2.0 to run this example. Aborting.", "GLSL not supported",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
this.Exit();
return;
}
GL.ClearColor(Color.MidnightBlue);
GL.Enable(EnableCap.DepthTest);
CreateVBO();
//CreateShader();
int status_code, status_text_length;
StringBuilder info = new StringBuilder();
vertex_shader_object = GL.CreateShader(Version20.VertexShader);
fragment_shader_object = GL.CreateShader(Version20.FragmentShader);
using (StreamReader sr = new StreamReader("Data/Shaders/Simple_VS.glsl"))
{
string[] code = new string[] { sr.ReadToEnd() };
#if MONO
unsafe { GL.ShaderSource(vertex_shader_object, vertex_shader_source.Length, vertex_shader_source, (int*)null); }
#else
GL.ShaderSource(vertex_shader_object, code.Length, code, (int[])null);
#endif
}
GL.CompileShader(vertex_shader_object);
GL.GetShader(vertex_shader_object, Version20.CompileStatus, out status_code);
GL.GetShader(vertex_shader_object, Version20.InfoLogLength, out status_text_length);
info.Remove(0, info.Length);
info.EnsureCapacity(status_text_length);
GL.GetShaderInfoLog(vertex_shader_object, info.Capacity, out status_text_length, info);
Trace.WriteLine(info.ToString());
if (status_code != 1)
throw new Exception(info.ToString());
using (StreamReader sr = new StreamReader("Data/Shaders/Simple_FS.glsl"))
{
string[] code = new string[] { sr.ReadToEnd() };
#if MONO
unsafe { GL.ShaderSource(fragment_shader_object, fragment_shader_source.Length, fragment_shader_source, (int*)null); }
#else
GL.ShaderSource(fragment_shader_object, code.Length, code, (int[])null);
#endif
}
GL.CompileShader(fragment_shader_object);
GL.GetShader(fragment_shader_object, Version20.CompileStatus, out status_code);
GL.GetShader(vertex_shader_object, Version20.InfoLogLength, out status_text_length);
info.Remove(0, info.Length);
info.EnsureCapacity(status_text_length);
GL.GetShaderInfoLog(fragment_shader_object, info.Capacity, out status_text_length, info);
Trace.WriteLine(info.ToString());
if (status_code != 1)
throw new Exception(info.ToString());
shader_program = GL.CreateProgram();
GL.AttachShader(shader_program, fragment_shader_object);
GL.AttachShader(shader_program, vertex_shader_object);
GL.LinkProgram(shader_program);
GL.UseProgram(shader_program);
}
private void CreateVBO()
{
int size;
GL.GenBuffers(1, out vertex_buffer_object);
GL.GenBuffers(1, out color_buffer_object);
GL.GenBuffers(1, out element_buffer_object);
// Upload the vertex data.
GL.BindBuffer(Version15.ArrayBuffer, vertex_buffer_object);
GL.BufferData(Version15.ArrayBuffer, (IntPtr)(shape.Vertices.Length * 3 * sizeof(float)), shape.Vertices, Version15.StaticDraw);
GL.GetBufferParameter(Version15.ArrayBuffer, Version15.BufferSize, out size);
if (size != shape.Vertices.Length * 3 * sizeof(Single))
throw new ApplicationException("Problem uploading vertex data to VBO");
// Upload the color data.
GL.BindBuffer(Version15.ArrayBuffer, color_buffer_object);
GL.BufferData(Version15.ArrayBuffer, (IntPtr)(shape.Colors.Length * sizeof(int)), shape.Colors, Version15.StaticDraw);
GL.GetBufferParameter(Version15.ArrayBuffer, Version15.BufferSize, out size);
if (shape.Colors.Length * sizeof(int) != size)
throw new ApplicationException("Problem uploading color data to VBO");
// Upload the index data (elements inside the vertex data, not color indices as per the IndexPointer function!)
GL.BindBuffer(Version15.ElementArrayBuffer, element_buffer_object);
GL.BufferData(Version15.ElementArrayBuffer, (IntPtr)(shape.Indices.Length * sizeof(Int32)), shape.Indices, Version15.StaticDraw);
GL.GetBufferParameter(Version15.ElementArrayBuffer, Version15.BufferSize, out size);
if (shape.Indices.Length * 4 != size)
throw new ApplicationException("Problem uploading index data to VBO");
}
#endregion
#region OnUnload
public override void OnUnload(EventArgs e)
{
if (shader_program != 0)
GL.DeleteProgram(shader_program);
if (fragment_shader_object != 0)
GL.DeleteShader(fragment_shader_object);
if (vertex_shader_object != 0)
GL.DeleteShader(vertex_shader_object);
if (vertex_buffer_object != 0)
GL.DeleteBuffers(1, ref vertex_buffer_object);
if (element_buffer_object != 0)
GL.DeleteBuffers(1, ref element_buffer_object);
}
#endregion
#region OnResize
/// <summary>
/// Called when the user resizes the window.
/// </summary>
/// <param name="e">Contains the new width/height of the window.</param>
/// <remarks>
/// You want the OpenGL viewport to match the window. This is the place to do it!
/// </remarks>
protected override void OnResize(OpenTK.Platform.ResizeEventArgs e)
{
GL.Viewport(0, 0, Width, Height);
double ratio = e.Width / (double)e.Height;
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
Glu.Perspective(45.0, ratio, 1.0, 64.0);
}
#endregion
#region OnUpdateFrame
/// <summary>
/// Prepares the next frame for rendering.
/// </summary>
/// <remarks>
/// Place your control logic here. This is the place to respond to user input,
/// update object positions etc.
/// </remarks>
public override void OnUpdateFrame(UpdateFrameEventArgs e)
{
if (Keyboard[OpenTK.Input.Key.Escape])
this.Exit();
if ((Keyboard[OpenTK.Input.Key.AltLeft] || Keyboard[OpenTK.Input.Key.AltRight]) &&
Keyboard[OpenTK.Input.Key.Enter])
Fullscreen = !Fullscreen;
}
#endregion
#region OnRenderFrame
/// <summary>
/// Place your rendering code here.
/// </summary>
public override void OnRenderFrame(RenderFrameEventArgs e)
{
GL.Clear(ClearBufferMask.ColorBufferBit |
ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
Glu.LookAt(0.0, 5.0, 5.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
angle += rotation_speed * (float)e.ScaleFactor;
GL.Rotate(angle, 0.0f, 1.0f, 0.0f);
GL.EnableClientState(EnableCap.VertexArray);
GL.EnableClientState(EnableCap.ColorArray);
GL.BindBuffer(Version15.ArrayBuffer, vertex_buffer_object);
GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(Version15.ArrayBuffer, color_buffer_object);
GL.ColorPointer(4, ColorPointerType.UnsignedByte, 0, IntPtr.Zero);
GL.BindBuffer(Version15.ElementArrayBuffer, element_buffer_object);
GL.DrawElements(BeginMode.Triangles, shape.Indices.Length,
All.UnsignedInt, IntPtr.Zero);
//GL.DrawArrays(GL.Enums.BeginMode.POINTS, 0, shape.Vertices.Length);
GL.DisableClientState(EnableCap.VertexArray);
GL.DisableClientState(EnableCap.ColorArray);
//int error = GL.GetError();
//if (error != 0)
// Debug.Print(Glu.ErrorString(Glu.Enums.ErrorCode.INVALID_OPERATION));
Context.SwapBuffers();
}
#endregion
#region IExample members
#region public void Launch()
/// <summary>
/// Launches this example.
/// </summary>
/// <remarks>
/// Provides a simple way for the example launcher to launch the examples.
/// </remarks>
public void Launch()
{
Run(30.0, 0.0);
}
#endregion
public static readonly int order = 10;
#endregion
}
}