Vertex Locations are off when using Mesa Core Prof

2019-09-21 03:19发布

问题:

I am using Mesa 10.1.3 to be able to use OpenGL 3.3 on my Linux computer. I request a core profile when I create the window since only the core profile has OpenGL 3.3. But when I tried to write a simple program to display a triangle on the screen, I got nothing. So I thought I screwed up somewhere in the code but I rechecked it and it was correct. To test this, I tried running the program in Windows and it was working as it should. So I experimented a little bit more with the code; I multiplied the vertex location in the vertex shader by 0.001 and only then I was able to see my triangle, but even then, it was not working as it should. The triangle I see was a right angle triangle whereas I intended it to be an equilateral one (in Windows I see an equilateral triangle). So my guess is vertex location is somehow different when using OpenGL Core profile, but I don't quite know how to fix this. What am I doing wrong and what should I be doing?

By the way, this is my vertex shader looks like:

#version 330

in vec3 position;

void main()
{
  gl_Position = vec4(0.001*position, 1.0);
}

Fragment shader:

#version 330

out vec4 fragColor;

void main()
{
  fragColor = vec4(0.0, 1.0, 1.0, 1.0);
}

Shader class:

public Shader()
    {
    program = glCreateProgram();
    if(program == 0)
    {
        System.err.println("Shader creation failed: Could not find valid memory location");
        System.exit(1);
    }
    }

    public void bind()
    {
    glBindAttribLocation(program, 0, "position");
    glUseProgram(program);
    }

    public void addVertexShader(String text)
    {
    addProgram(text, GL_VERTEX_SHADER);
    }

    public void addFragmentShader(String text)
    {
    addProgram(text, GL_FRAGMENT_SHADER);
    }

    public void addGeometryShader(String text)
    {
    addProgram(text, GL_GEOMETRY_SHADER);
    }

    public void compile()
    {
    glLinkProgram(program);

    if(glGetProgrami(program, GL_LINK_STATUS) == 0)
    {
        System.err.println(glGetProgramInfoLog(program, 1024));
        System.exit(1);
    }

    glValidateProgram(program);

    if(glGetProgrami(program, GL_VALIDATE_STATUS) == 0)
    {
        System.err.println(glGetProgramInfoLog(program, 1024));
        System.exit(1);
    }
    }

    public void addProgram(String text, int type)
    {
    int shader = glCreateShader(type);

    if(shader == 0)
    {
        System.err.println("Shader creation failed");
        System.exit(1);
    }

    glShaderSource(shader, text);
    glCompileShader(shader);

    if(glGetShaderi(shader, GL_COMPILE_STATUS) == 0)
    {
        System.err.println(glGetShaderInfoLog(shader, 1024));
        System.exit(1);
    }

    glAttachShader(program, shader);

    }

And my array of vertices which I'm creating the VBO with:

Vertex[] data = new Vertex[] {            
new Vertex(new Vector3f(-0.1f, -0.1f, 0)),
new Vertex(new Vector3f(0,  1, 0)),
new Vertex(new Vector3f( 1,  -1, 0))};

My draw method:

public void draw()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//Vertex is a class which only holds a Vector3f for position, currently, so size is set to 3
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glDrawArrays(GL_TRIANGLES, 0, size);
glDisableVertexAttribArray(0);
}

And this is the result that I'm getting:

回答1:

Your glBindAttribLocation() call comes too late:

glBindAttribLocation(program, 0, "position");
glUseProgram(program);

glBindAttribLocation() needs to be called before the glLinkProgram() to have any effect. You can move it, or use glGetAttribLocation() after linking to get the location that the linker assigned to the attribute. Or even easier, since you use GLSL 3.30, you can specify the location in the shader code:

layout(location = 0) in vec3 position;

When using the Core Profile, you will also need to use Vertex Array Objects (VAO). If you don't have calls like glGenVertexArrays() and glBindVertexArray() in your code, you will need those. There should be plenty of examples here on SO or on the rest of the internet if you search for "OpenGL VAO" or "OpenGL Vertex Array Object", so I won't repeat too much of it. Roughly, you will have something like this before you start initializing your vertex state:

GLuint vaoId = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// calls to glVertexAttribPointer, glEnableVertexAttribArray

Then when you get ready to draw:

glBindVertexArray(vao);

Your vertex data definition also looks like it could be a source of trouble:

Vertex[] data = new Vertex[] {            
new Vertex(new Vector3f(-0.1f, -0.1f, 0)),
new Vertex(new Vector3f(0,  1, 0)),
new Vertex(new Vector3f( 1,  -1, 0))};

While the code for filling this into the VBO is not shown, the data passed to glBufferData() needs to be a flat, contiguous array/buffer of floats, while this is an array of vector object references.