0

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)
            });

2 Answers2

0

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.

-1

Try adding flat to both the out and in of rgb. This prevents an interpolation step and maps the vertex output directly to the fragment input. While it may not give you the result you want with the triangle colouring, it will help you to isolate the issue.

rubics5
  • 21
  • 5
  • He's passing a *constant value*; how could it be interpolated? – Nicol Bolas Nov 14 '16 at 03:36
  • @NicolBolas you are right, I am probably off base on this one. I misremembered a similar issue I had when trying to pass integers from vertex to fragment shaders, for which `flat` is required. – rubics5 Nov 14 '16 at 04:20