I want to draw instanced cubes.
I can call GL.DrawArraysInstanced(PrimitiveType.Triangles, 0, 36, 2);
successfully.
My problem is that all the cubes are drawn at the same position and same rotation. How can i change that individually for every cube?
To create different positions and so on, i need a matrix for each cube, right? I created this:
Matrix4[] Matrices = new Matrix4[]{
Matrix4.Identity, //do nothing
Matrix4.Identity * Matrix4.CreateTranslation(1,0,0) //move a little bit
};
GL.BindBuffer(BufferTarget.ArrayBuffer, matrixBuffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(sizeof(float) * 16 * Matrices.Length), Matrices, BufferUsageHint.StaticDraw);
This should create a buffer where i can store my matrices. matrixBuffer
is the pointer to my buffer. Im not sure if the size is correct, i took float * 4 (for Vector4) * 4 (for 4 vectors) * array-size.
Draw Loop:
GL.BindBuffer(BufferTarget.ArrayBuffer, matrixBuffer);
GL.VertexAttribPointer(3, 4, VertexAttribPointerType.Float, false, 0, 0);
//GL.VertexAttribDivisor(3, ?);
GL.EnableVertexAttribArray(3);
GL.DrawArraysInstanced(PrimitiveType.Triangles, 0, 36, 2);
Any higher number than 4 in VertexAttribPointer(..., 4, VertexattribPointerType.Float, ...);
causes a crash. I tought i have to set that value to 16?
Im not sure if i need a VertexAttribDivisor, probably i need this every 36th vertex so i call GL.VertexAttribDivisor(3, 36);
? But when i do that, i can't see any cube.
My vertex shader:
#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
layout(location = 2) in vec2 texCoord;
layout(location = 3) in mat4 instanceMatrix;
uniform mat4 projMatrix;
out vec4 vColor;
out vec2 texCoords[];
void main(){
gl_Position = instanceMatrix * projMatrix * vec4(position, 1.0);
//gl_Position = projMatrix * vec4(position, 1.0);
texCoords[0] = texCoord;
vColor = color;
}
So my questions:
- What is wrong with my code?
- Why can i set the size-parameter of VertexAttribPointer only to 4?
- What is the correct value for VertexAttribDivisor?
Edit:
Based on the answer of Andon M. Coleman i made this changes:
GL.BindBuffer(BufferTarget.UniformBuffer, matrixBuffer);
GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)(sizeof(float) * 16), IntPtr.Zero, BufferUsageHint.DynamicDraw);
//Bind Buffer to Binding Point
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, matrixUniform, matrixBuffer);
matrixUniform = GL.GetUniformBlockIndex(shaderProgram, "instanceMatrix");
//Bind Uniform Block to Binding Point
GL.UniformBlockBinding(shaderProgram, matrixUniform, 0);
GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, (IntPtr)(sizeof(float) * 16 * Matrices.Length), Matrices);
And shader:
#version 330 core
layout(location = 0) in vec4 position; //gets vec3, fills w with 1.0
layout(location = 1) in vec4 color;
layout(location = 2) in vec2 texCoord;
uniform mat4 projMatrix;
uniform UniformBlock
{ mat4 instanceMatrix[]; };
out vec4 vColor;
out vec2 texCoords[];
void main(){
gl_Position = projMatrix * instanceMatrix[0] * position;
texCoords[0] = texCoord;
vColor = color;
}