Search code examples
openglsharpgl

Can't pass color from vertex shader to fragment shader


I'm new to OpenGL and study it using SharpGL which is simple C# binding to OpenGL functions.I'm trying to use the simplest vertex and fragment shaders. When fragment shader generates output by itself, everything is fine, but when it tries to use data which came from vertex shader, there's only a black screen. Shaders are successfully compiled and linked to a program. No errors were returned by OpenGL. After tons of articles, examples and tutorials I still have no idea why it happens. Here's vertex shader.

#version 330

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;

out vec3 rgb;

void main()
{
    rgb = vec3(1.0, 0.5, 0.5);
    gl_Position = vec4(position,  1.0);
}

Fragment shader:

#version 330

in vec3 rgb;

out vec3 outColor;

void main()
{
    //outColor = rgb; // black display
    outColor = vec3(1.0, 0.0, 0.4); // works fine
}

Here's initialization code:

gl.GenVertexArrays(1, arrayBuffer);
gl.BindVertexArray(arrayBuffer[0]);

gl.GenBuffers(1, pointsBuffer);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, pointsBuffer[0]);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, triangle, OpenGL.GL_STATIC_DRAW);

gl.GenBuffers(1, colorsBuffer);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, colorsBuffer[0]);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, colors, OpenGL.GL_STATIC_DRAW);

And finally here's what's happend on every iteration:

gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

gl.UseProgram(program.Id);

gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, pointsBuffer[0]);
gl.EnableVertexAttribArray(0);
gl.VertexAttribPointer(0, 3, OpenGL.GL_FLOAT, false, 0, IntPtr.Zero);

gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, colorsBuffer[0]);
gl.EnableVertexAttribArray(1);
gl.VertexAttribPointer(1, 3, OpenGL.GL_FLOAT, false, 0, IntPtr.Zero);

gl.DrawArrays(OpenGL.GL_TRIANGLES, 0, 12);

gl.DisableVertexAttribArray(0);
gl.DisableVertexAttribArray(1);

UPD 1. Here's the data passed to buffers.

private float[] triangle = {
    -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    0.0f, 0.5f, 0.0f, 
};

private float[] colors = {
    1.0f, 0.0f, 0.0f,
    0.5f, 1.0f, 0.0f,
    0.0f, 0.5f, 0.0f
};
private uint[] arrayBuffer = new uint[1];
private uint[] pointsBuffer = new uint[1];
private uint[] colorsBuffer = new uint[1];

UPD 2 Here's shaders compilation code

private uint CompileProgram(OpenGL gl, List<ShaderMetadata> shaders)
{
    var program = gl.CreateProgram();

    shaders.ForEach(shader => gl.AttachShader(program, CompileShader(gl, shader.Path, shader.Mode)));

    gl.LinkProgram(program);

    var status = ProgramErrorInfo(gl, program);
    if (!String.IsNullOrEmpty(status))
    {
        throw new ArgumentException(status);
    }

    return program;
}

private uint CompileShader(OpenGL gl, string path, uint kind)
{
    using (var fs = new FileStream(path, FileMode.Open))
    {
        using (var reader = new StreamReader(fs))
        {
            var program = reader.ReadToEnd();
            var id = gl.CreateShader(kind);
            gl.ShaderSource(id, program);
            gl.CompileShader(id);

            var status = ShaderErrorInfo(gl, id);
            if (!String.IsNullOrEmpty(status))
            {
                throw new ArgumentException(status);
            }

            return id;
        }
    }
}

private string ShaderErrorInfo(OpenGL gl, uint shaderId)
{
    StringBuilder builder = new StringBuilder(2048);
    gl.GetShaderInfoLog(shaderId, 2048, IntPtr.Zero, builder);
    return builder.ToString();
}

private string ProgramErrorInfo(OpenGL gl, uint programId)
{
    StringBuilder builder = new StringBuilder(2048);
    gl.GetProgramInfoLog(programId, 2048, IntPtr.Zero, builder);
    return builder.ToString();
}

UPD 3 And here's how compiler is invoked

var programId = CompileProgram(gl, new List<ShaderMetadata>
            {
                new ShaderMetadata(
                    @"vertex.shader",
                    OpenGL.GL_VERTEX_SHADER),
                new ShaderMetadata(
                    @"fragment.shader",
                    OpenGL.GL_FRAGMENT_SHADER)
            });

Solution

  • Well, it was resolved by unmounting a shader program after drawing:

    gl.DrawArrays(OpenGL.GL_TRIANGLES, 0, 12);
    gl.UseProgram(0);
    

    Anyway, if anyone has an explanation or a reference to doc or something, you are welcome.