kkc0923's picture

Shader can't receive Vertex Buffer Data (Solved)

Sorry for too many questions in short time, I have one more questions.

I implemented simple mesh drawing component, part of source code is below.

Generate & Fill Buffer

if (Positions != null)
            {
                positionBufferObject = GL.GenBuffer();
 
                Vector3F[] bufferData = new Vector3F[length];
 
                for (int i = 0; i < Positions.Length; i++)
                {
                    bufferData[i] = Positions[i].ToFloat();
                }
 
                GL.BindBuffer(BufferTarget.ArrayBuffer, positionBufferObject);
                GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(length * 12), bufferData, BufferUsageHint.DynamicDraw);
            }
            if (Colors != null)
            {
                colorBufferObject = GL.GenBuffer();
                Color4F[] bufferData = new Color4F[length];
 
                for (int i = 0; i < Colors.Length; i++)
                {
                    bufferData[i] = Colors[i].ToFloat();
                }
 
                GL.BindBuffer(BufferTarget.ArrayBuffer, colorBufferObject);
                GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(length * 16), bufferData, BufferUsageHint.DynamicDraw);
            }

Mesh Rendering Method

public void Draw()
        {
            GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
            GL.CullFace(CullFaceMode.Back);
 
            if (positionBufferObject > 0)
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, positionBufferObject);
                GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
                GL.EnableVertexAttribArray(0);
            }
 
            if (colorBufferObject > 0)
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, colorBufferObject);
                GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, 0, 0);
                GL.EnableVertexAttribArray(2);
            }
 
            GL.DrawArrays(PrimitiveType.Triangles, 0, length);
 
            GL.DisableVertexAttribArray(0);
            GL.DisableVertexAttribArray(1);
            GL.DisableVertexAttribArray(2);
        }

Main Rendering Method

int worldLocation = GL.GetUniformLocation(program, "world");
                    int viewLocation = GL.GetUniformLocation(program, "view");
                    int projectionLocation = GL.GetUniformLocation(program, "projection");
 
                    OpenTK.Matrix4 world = transform.World.ToOpenTK();
                    OpenTK.Matrix4 view = Camera.View.ToOpenTK();
                    OpenTK.Matrix4 projection = Camera.Projection.ToOpenTK();
 
                    GL.UniformMatrix4(worldLocation, false, ref world);
                    GL.UniformMatrix4(viewLocation, false, ref view);
                    GL.UniformMatrix4(projectionLocation, false, ref projection);
 
                    GL.BindAttribLocation(program, 0, "position");
                    GL.BindAttribLocation(program, 1, "normal");
                    GL.BindAttribLocation(program, 2, "color");
 
                    mesh.Draw();

Shader code is here.

Vertex Shader

#version 440
 
uniform mat4 world;
uniform mat4 view;
uniform mat4 projection;
 
in vec3 position;
in vec3 normal;
in vec4 color;
 
out vec4 vscolor;
 
void main()
{
	gl_Position = projection * view * world * vec4(position, 1.0);
	vscolor = color;
}

Fragment Shader

#version 440
 
in vec4 vscolor;
out vec4 fscolor;
 
void main()
{
	fscolor = vscolor;
}

But when I run this app, vertex color is always RED until I filled color buffer with all of White value (1 1 1 1).

What is problem of this code?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kkc0923's picture

I solve this problem myself :)

I found that BindAttribLocation() is not working after shader linking. So I modified my shader code to manually set attribute location using layout(location = #) keyword. And bind to manual location, all of meshes are drawn correctly.

ElectricFountainCo's picture

Hey, can you give me a sample of what you did. I am still trying to link my code with my shader, and it's a bleepin pain in the as s.

kkc0923's picture

I modified my vertex shader like this. (add layout (location =#) to input data.)

#version 440
 
uniform mat4 world;
uniform mat4 view;
uniform mat4 projection;
 
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
 
out vec4 vscolor;
 
void main()
{
	gl_Position = projection * view * world * vec4(position, 1.0);
	vscolor = color;
}

Then, bind my vertex buffer to directly layout number (in this case, position buffer is 0, color buffer is 1)

GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, positionBufferObject);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 12, 0);
 
GL.EnableVertexAttribArray(1);
GL.BindBuffer(BufferTarget.ArrayBuffer, colorBufferObject);
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, 16, 0);

And transfer world, projection, view matrix data. (view, world, projection is 4x4 matrix structure.)

viewLocation = GL.GetUniformLocation(program, "view");
projectionLocation = GL.GetUniformLocation(program, "projection");
worldLocation = GL.GetUniformLocation(program, "world");
 
GL.UniformMatrix4(shader.ViewLocation, false, ref view);
GL.UniformMatrix4(shader.ProjectionLocation, false, ref projection);
GL.UniformMatrix4(shader.WorldLocation, false, ref world);

After all, simply call draw method.

GL.BindVertexArray(vertexArrayObject);
GL.DrawArrays(PrimitiveType.Triangles, 0, length);

PS. Vertex Array Object generation code is not showed because my code is too long. You should make your own vertex array object.