#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2009 the Open Toolkit library.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
using System;
using System.Diagnostics;
using System.IO;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace Examples
.Tutorial
{
[Example
("OpenGL 3.0", ExampleCategory
.OpenGL,
"3.x", Documentation
="HelloGL3")]
public class HelloGL3
: GameWindow
{
string vertexShaderSource
= @"
#version 130
precision highp float;
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
in vec3 in_position;
in vec3 in_normal;
out vec3 normal;
void main(void)
{
//works only for orthogonal modelview
normal = (modelview_matrix * vec4(in_normal, 0)).xyz;
gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);
}";
string fragmentShaderSource
= @"
#version 130
precision highp float;
const vec3 ambient = vec3(0.1, 0.1, 0.1);
const vec3 lightVecNormalized = normalize(vec3(0.5, 0.5, 2.0));
const vec3 lightColor = vec3(0.9, 0.9, 0.7);
in vec3 normal;
out vec4 out_frag_color;
void main(void)
{
float diffuse = clamp(dot(lightVecNormalized, normalize(normal)), 0.0, 1.0);
out_frag_color = vec4(ambient + diffuse * lightColor, 1.0);
}";
int vertexShaderHandle,
fragmentShaderHandle,
shaderProgramHandle,
modelviewMatrixLocation,
projectionMatrixLocation,
vaoHandle,
positionVboHandle,
normalVboHandle,
eboHandle
;
Vector3
[] positionVboData
= new Vector3
[]{
new Vector3
(-1
.0f,
-1
.0f, 1
.0f
),
new Vector3
( 1
.0f,
-1
.0f, 1
.0f
),
new Vector3
( 1
.0f, 1
.0f, 1
.0f
),
new Vector3
(-1
.0f, 1
.0f, 1
.0f
),
new Vector3
(-1
.0f,
-1
.0f,
-1
.0f
),
new Vector3
( 1
.0f,
-1
.0f,
-1
.0f
),
new Vector3
( 1
.0f, 1
.0f,
-1
.0f
),
new Vector3
(-1
.0f, 1
.0f,
-1
.0f
) };
int[] indicesVboData
= new int[]{
// front face
0,
1,
2,
2,
3,
0,
// top face
3,
2,
6,
6,
7,
3,
// back face
7,
6,
5,
5,
4,
7,
// left face
4,
0,
3,
3,
7,
4,
// bottom face
0,
1,
5,
5,
4,
0,
// right face
1,
5,
6,
6,
2,
1,
};
Matrix4 projectionMatrix, modelviewMatrix
;
public HelloGL3
()
: base(640,
480,
new GraphicsMode
(),
"OpenGL 3 Example",
0,
DisplayDevice
.Default,
3,
0,
GraphicsContextFlags
.ForwardCompatible | GraphicsContextFlags
.Debug)
{ }
protected override void OnLoad
(System.EventArgs e
)
{
VSync
= VSyncMode
.On;
CreateShaders
();
CreateVBOs
();
CreateVAOs
();
// Other state
GL
.Enable(EnableCap
.DepthTest);
GL
.ClearColor(System.Drawing.Color.MidnightBlue);
}
void CreateShaders
()
{
vertexShaderHandle
= GL
.CreateShader(ShaderType
.VertexShader);
fragmentShaderHandle
= GL
.CreateShader(ShaderType
.FragmentShader);
GL
.ShaderSource(vertexShaderHandle, vertexShaderSource
);
GL
.ShaderSource(fragmentShaderHandle, fragmentShaderSource
);
GL
.CompileShader(vertexShaderHandle
);
GL
.CompileShader(fragmentShaderHandle
);
Debug
.WriteLine(GL
.GetShaderInfoLog(vertexShaderHandle
));
Debug
.WriteLine(GL
.GetShaderInfoLog(fragmentShaderHandle
));
// Create program
shaderProgramHandle
= GL
.CreateProgram();
GL
.AttachShader(shaderProgramHandle, vertexShaderHandle
);
GL
.AttachShader(shaderProgramHandle, fragmentShaderHandle
);
GL
.LinkProgram(shaderProgramHandle
);
Debug
.WriteLine(GL
.GetProgramInfoLog(shaderProgramHandle
));
GL
.UseProgram(shaderProgramHandle
);
// Set uniforms
projectionMatrixLocation
= GL
.GetUniformLocation(shaderProgramHandle,
"projection_matrix");
modelviewMatrixLocation
= GL
.GetUniformLocation(shaderProgramHandle,
"modelview_matrix");
float aspectRatio
= ClientSize
.Width / (float)(ClientSize
.Height);
Matrix4
.CreatePerspectiveFieldOfView((float)Math
.PI / 4, aspectRatio,
1,
100,
out projectionMatrix
);
modelviewMatrix
= Matrix4
.LookAt(new Vector3
(0,
3,
5),
new Vector3
(0,
0,
0),
new Vector3
(0,
1,
0));
GL
.UniformMatrix4(projectionMatrixLocation,
false,
ref projectionMatrix
);
GL
.UniformMatrix4(modelviewMatrixLocation,
false,
ref modelviewMatrix
);
}
void CreateVBOs
()
{
GL
.GenBuffers(1,
out positionVboHandle
);
GL
.BindBuffer(BufferTarget
.ArrayBuffer, positionVboHandle
);
GL
.BufferData<Vector3
>(BufferTarget
.ArrayBuffer,
new IntPtr
(positionVboData
.Length * Vector3
.SizeInBytes),
positionVboData, BufferUsageHint
.StaticDraw);
GL
.GenBuffers(1,
out normalVboHandle
);
GL
.BindBuffer(BufferTarget
.ArrayBuffer, normalVboHandle
);
GL
.BufferData<Vector3
>(BufferTarget
.ArrayBuffer,
new IntPtr
(positionVboData
.Length * Vector3
.SizeInBytes),
positionVboData, BufferUsageHint
.StaticDraw);
GL
.GenBuffers(1,
out eboHandle
);
GL
.BindBuffer(BufferTarget
.ElementArrayBuffer, eboHandle
);
GL
.BufferData(BufferTarget
.ElementArrayBuffer,
new IntPtr
(sizeof(uint) * indicesVboData
.Length),
indicesVboData, BufferUsageHint
.StaticDraw);
GL
.BindBuffer(BufferTarget
.ArrayBuffer,
0);
GL
.BindBuffer(BufferTarget
.ElementArrayBuffer,
0);
}
void CreateVAOs
()
{
// GL3 allows us to store the vertex layout in a "vertex array object" (VAO).
// This means we do not have to re-issue VertexAttribPointer calls
// every time we try to use a different vertex layout - these calls are
// stored in the VAO so we simply need to bind the correct VAO.
GL
.GenVertexArrays(1,
out vaoHandle
);
GL
.BindVertexArray(vaoHandle
);
GL
.EnableVertexAttribArray(0);
GL
.BindBuffer(BufferTarget
.ArrayBuffer, positionVboHandle
);
GL
.VertexAttribPointer(0,
3, VertexAttribPointerType
.Float,
true, Vector3
.SizeInBytes,
0);
GL
.BindAttribLocation(shaderProgramHandle,
0,
"in_position");
GL
.EnableVertexAttribArray(1);
GL
.BindBuffer(BufferTarget
.ArrayBuffer, normalVboHandle
);
GL
.VertexAttribPointer(1,
3, VertexAttribPointerType
.Float,
true, Vector3
.SizeInBytes,
0);
GL
.BindAttribLocation(shaderProgramHandle,
1,
"in_normal");
GL
.BindBuffer(BufferTarget
.ElementArrayBuffer, eboHandle
);
GL
.BindVertexArray(0);
}
protected override void OnUpdateFrame
(FrameEventArgs e
)
{
Matrix4 rotation
= Matrix4
.CreateRotationY((float)e
.Time);
Matrix4
.Mult(ref rotation,
ref modelviewMatrix,
out modelviewMatrix
);
GL
.UniformMatrix4(modelviewMatrixLocation,
false,
ref modelviewMatrix
);
if (Keyboard
[OpenTK
.Input.Key.Escape])
Exit
();
}
protected override void OnRenderFrame
(FrameEventArgs e
)
{
GL
.Viewport(0,
0, Width, Height
);
GL
.Clear(ClearBufferMask
.ColorBufferBit | ClearBufferMask
.DepthBufferBit);
GL
.BindVertexArray(vaoHandle
);
GL
.DrawElements(BeginMode
.Triangles, indicesVboData
.Length,
DrawElementsType
.UnsignedInt, IntPtr
.Zero);
SwapBuffers
();
}
[STAThread
]
public static void Main
()
{
using (HelloGL3 example
= new HelloGL3
())
{
Utilities
.SetWindowTitle(example
);
example
.Run(30);
}
}
}
}