-
Notifications
You must be signed in to change notification settings - Fork 110
Wiki \ How Do I
This page is trying to guide the user to the API; this is not a tutorial about OpenGL itself. It focuses on the API design, such as overrides and special variations with respect to the C style API.
OpenGL functions have the same name as the GL specification but without the namespace prefix ('gl', 'egl', 'wgl' and 'glX') and the argument type suffixes ('f', 'd', 'ui', etc...).
Gl.Viewport(0, 0, 800, 600);
Gl.Clear(ClearBufferMask.ColorBufferBit);
Gl.Begin(PrimitiveType.Triangles);
Gl.Color3(1.0f, 0.0f, 0.0f); Gl.Vertex2(0.0f, 0.0f);
Gl.Color3(0.0f, 1.0f, 0.0f); Gl.Vertex2(0.5f, 1.0f);
Gl.Color3(0.0f, 0.0f, 1.0f); Gl.Vertex2(1.0f, 0.0f);
Gl.End();
Create a simple buffer objects:
float[] buffer = new[] { ... };
// Equivalent to glGenBuffers(1, &obj)
uint obj = Gl.GenBuffer();
Gl.BindBuffer(BufferTarget.ArrayBuffer, obj);
Gl.BufferData(BufferTarget.ArrayBuffer, (uint)(4 * buffer.Length), buffer, BufferUsage.StaticDraw);
public uint CreateShader()
{
string[] source = {
"#version 150 compatibility\n",
"uniform mat4 uMVP;\n",
"in vec2 aPosition;\n",
"in vec3 aColor;\n",
"out vec3 vColor;\n",
"void main() {\n",
" gl_Position = uMVP * vec4(aPosition, 0.0, 1.0);\n",
" vColor = aColor;\n",
"}\n"
};
uint obj = Gl.CreateShader(ShaderType.VertexShader);
Gl.ShaderSource(ShaderName, source);
Gl.CompileShader(ShaderName);
int compiled;
Gl.GetShader(ShaderName, ShaderParameterName.CompileStatus, out compiled);
if (compiled != 0)
return obj;
// Not compiled!
Gl.DeleteShader(obj);
const int logMaxLength = 1024;
StringBuilder infolog = new StringBuilder(logMaxLength);
int infologLength;
Gl.GetShaderInfoLog(ShaderName, logMaxLength, out infologLength, infolog);
throw new InvalidOperationException($"unable to compile shader: {infolog}");
}
Gl.Uniform3(0, 1.0f, 1.0f, 1.0f); // layout(location = 0) uniform vec3 v;
Gl.Uniform1(0, 1.0f); // layout(location = 0) uniform float v;
Gl.Uniform1(0, 1); // layout(location = 0) uniform int v;
You have also reference overloads: they take a blittable structures with the proper layout.
Vertex3f v1 = Vertex3f.UnitX;
Gl.Uniform3f(0, 1 /* count */, v1); // layout(location = 0) uniform vec3 v;
Gl.UniformMatrix2(0, false, new[] { 1.0f, 0.0f, 0.0f, 1.0f }); // layout(location = 0) uniform mat2 m;
// Matrix types have (explicit) cast defined
Gl.UniformMatrix4(0, false, (float[])Matrix4x4f.Ortho2D(0.0f, 1.0f, 0.0f, 1.0f)); // layout(location = 0) uniform mat4 m;
Although the above lines are functional, they allocate an array. To avoid performance issues, use generic overrides (note the suffix).
Matrix4x4f m = Matrix4x4f.Ortho2D(0.0f, 1.0f, 0.0f, 1.0f);
Gl.UniformMatrix4f(0, 1, false, m); // layout(location = 0) uniform mat4 m;
Matrix4x4d dm = Matrix4x4d.Ortho2D(0.0, 1.0, 0.0, 1.0);
Gl.UniformMatrix4d(0, 1, false, dm); // layout(location = 0) uniform dmat4 m;
Type safety is good, but it doesn't help here, and we have to deal with pointers; fortunately we have unsafe overloads.
Vertex4i[] v = new Vertex4i[4];
unsafe {
fixed (Vertex4i* p_v = v) {
Gl.Uniform4(0, v.Length, (int*)p_v); // layout(location = 0) uniform ivec4 v[4];
}
}
Matrix4x4f m = new Matrix4x4f[16];
unsafe {
fixed (Matrix4x4f* p_m = m) {
Gl.UniformMatrix4f(0, m.Length, false, (float*)p_v); // layout(location = 0) uniform mat4 m[16];
}
}
Using OpenGL.Net.Math package you can execute math on CPU. This is necessary for passing information to the shader programs. Available structures are matrices, vertices, and quaternions.
Vertex3f v1 = new Vertex3f(); // XYZ zeroed
Vertex4f v2 = new Vertex4f(); // XYZW zeroed
Vertex2f v3 = new Vertex2f(1.0f, 2.0f);
Vertex4f v4 = new Vertex4f(2.3f); // XYZW have same values
Vertex2ui v5 = Vertex2ui.UnitX; // X unit vector
Vertex4f x = Vertex4f.UnitX; // (1, 0, 0, 1)
Vertex4f v1 = new Vertex4f(10.0f, 10.0f, 10.0f, 10.0f);
Vertex3f v2 = new Vertex3f(1.0f, 1.0f, 1.0f);
Vertex3f v3 = (Vertex3f)v1;
Debug.Assert(v3 == v2);
Matrix4x4f ortho = Matrix4x4f.Ortho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, 1.0f);
Matrix4x4f ortho2D = Matrix4x4f.Ortho2D(-1.0f, +1.0f, -1.0f, +1.0f); // As above
Matrix4x4f perspective = Matrix4x4f.Perspective(45.0f, 1.0f, 0.1f, 1000.0f); // Symmetric
Matrix4x4f translate = Matrix4x4f.Translated(-1.0f, +1.0f, -1.0f);
Matrix4x4f rotateX = Matrix4x4f.RotatedX(30.0f);
Matrix4x4f scale = Matrix4x4f.Scaled(0.1f, 1.0f, 2.0f);
Matrix4x4f p = Matrix4x4f.Ortho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, 1.0f);
Matrix4x4f v = Matrix4x4f.Translated(0.0f, 0.0f, 10.0f).Inverse;
Matrix4x4f m = Matrix4x4f.Identity;
Matrix4x4f mvp = p * v * m;
Matrix4x4f mv = Matrix4x4f.Identity;
Matrix3x3f n = new Matrix3x3f(mv, 3, 3).Inverse.Transposed
Matrix4x4f p = Matrix4x4f.Ortho(-1.0f, +1.0f, -1.0f, +1.0f, -10.0f, 10.0f);
Matrix4x4f v = Matrix4x4f.Translated(0.0f, 0.0f, 10.0f).Inverse;
Matrix4x4f m = Matrix4x4f.Identity;
Matrix4x4f mvp = p * v * m;
Vertex4f v = new Vertex4f(0.0f, 0.0f, 0.0f); // (0, 0, 0, 1)
Vertex3f r = (Vertex3f)(mvp * v); // (0, 0, -10)