Jump to content
  • Advertisement
Sign in to follow this  
mojobojo

C and GLSL vec3 Position and Color Problem

This topic is 1157 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So in my render loop I am trying to draw a GL_POINT with a color. I have a shader that it runs through for matrix transformations. For some reason I can set the color, set the position, but not both. When I set the color the positions gl_Position gets messed up for some reason. I am sure this boils down to me not knowing much about GLSL. If somebody could help that would be great.

 

C code

internal void
Render(game_memory *Memory)
{
    game_state *GameState = (game_state *)Memory->PermanentStorage;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glm::mat4 Model = glm::mat4(1.0f);
    glm::mat4 Projection = glm::ortho(0.0f, 1280.0f, 720.0f, 0.0f, 0.0f, 1.0f);

    GLint ModelUniform = glGetUniformLocation(GameState->ShaderProgram, "Model");
    Assert(ModelUniform != -1);
    glUniformMatrix4fv(ModelUniform, 1, GL_FALSE, glm::value_ptr(Model));

    GLint ProjectionUniform = glGetUniformLocation(GameState->ShaderProgram, "Projection");
    Assert(ProjectionUniform != -1);
    glUniformMatrix4fv(ProjectionUniform, 1, GL_FALSE, glm::value_ptr(Projection));

    r32 SinOfTime = sinf(GameState->ElapsedTime);
    r32 CosOfTime = cosf(GameState->ElapsedTime);

    v2 Location;
    Location.x = 500.0f + 100.0f * SinOfTime;
    Location.y = 500.0f + 100.0f * CosOfTime;

    glDisable(GL_TEXTURE_2D);
    glPointSize(10.0f);
    glBegin(GL_POINTS);
    glColor3f(fabs(SinOfTime), 0.0f, 0.0f);
    glVertex3f(Location.x, Location.y, 0.0f);
    glEnd();
    glEnable(GL_TEXTURE_2D);

    SDL_GL_SwapWindow(GameState->SdlWindow);
}

Additional code that sets the position attribute so I can use it.

    GLint PosAttrib = glGetAttribLocation(GameState->ShaderProgram, "position");
    glEnableVertexAttribArray(PosAttrib);
    glVertexAttribPointer(PosAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);

Fragment Shader

#version 130

in vec4 Color;

void main(void)
{
    gl_FragColor = Color;
}

Vertex Shader

#version 130

in vec3 position;
out vec4 Color;
uniform mat4 Model;
uniform mat4 Projection;

void main(void)
{
    Color = gl_Color; // If I comment this line out and not set the color the
                      // position sets fine. If its like this, color changes
                      // but the position sticks in the top left corner of 
                      // the screen.
    gl_Position = Projection * Model * vec4(position, 1.0);
}

Share this post


Link to post
Share on other sites
Advertisement
You are mixing so many GL versions it's a little hard to track what all could be going wrong.

I'd advise explicitly declaring a colour attribute, rather than relying on the built-in gl_Color input - not all drivers properly support mixing and matching between generic and built-in attributes.

Share this post


Link to post
Share on other sites

You are mixing so many GL versions it's a little hard to track what all could be going wrong.

I'd advise explicitly declaring a colour attribute, rather than relying on the built-in gl_Color input - not all drivers properly support mixing and matching between generic and built-in attributes.

 

Because of the lack of up to date or concise guides out there I guess its no surprise my code looks like mixed GL versions. It would be nice to know what I am mixing and why its wrong. And I did as well try defining a color attribute with the same result. 

Share this post


Link to post
Share on other sites

It would be nice to know what I am mixing and why its wrong.

It's not wrong, per se - unless you explicitly tell OpenGL that you want a Core/ForwardCompatible context, you can freely mix versions. It is however confusing to the reader smile.png

Typically, one doesn't mix built-in attributes with generic attributes (i.e. use gl_Vertex and gl_Color, or provide both as generic attributes), nor mix shaders with immediate mode (glBegin/glEnd - prefer glDrawArrays/glDrawElements and vertex buffers).

In this case, I think the issue is that you are both providing a position through glVertexAttribPointer(), and via glVertex(). Or, in other words, you are providing 3 peices of vertex data (glVertexAttribPointer, glVertex, glColor), and only consuming 2.

Share this post


Link to post
Share on other sites

In this case, I think the issue is that you are both providing a position through glVertexAttribPointer(), and via glVertex(). Or, in other words, you are providing 3 peices of vertex data (glVertexAttribPointer, glVertex, glColor), and only consuming 2.

 

 

I seem to have a misunderstanding as to how glColor and glVertex get passed into the shader perhaps. I thought I had to use glVertexAttribPointer to specify what I wanted to get passed to the shader.

 

EDIT:

Okay so I am starting to understand whats going on here. I got it working by removing the position input and doing. So if I understand correctly glVertex goes into gl_Vertex just as glColor goes into gl_Color?

void main(void)
{
    Color = gl_Color;
    gl_Position = Projection * Model * gl_Vertex;
}

Edited by mojobojo

Share this post


Link to post
Share on other sites

Okay so I am starting to understand whats going on here. I got it working by removing the position input and doing. So if I understand correctly glVertex goes into gl_Vertex just as glColor goes into gl_Color?

Yes. That is the legacy mechanism for defining vertex data.

These days, one would specify both position and colour as explicit attributes in the shader, store the actual data for each one in a vertex buffer, bind each one with glVertexAttribPointer, and draw them using glDrawArrays.

Share this post


Link to post
Share on other sites

What version of OpenGL do you want to use?

I am thinking 3.1. It is what I am telling SDL to initialize to and it seems like its what most people have. Is there any good reason to target 4.x? I don't have a set in stone target version simply because I am just exploring right now but I am open to suggestions. For right now I just want my own little sandbox where I can play around with 2D graphics using modern OpenGL and GLSL.

 

I am looking into drawing the points another way right now. Its not working but I think I am on the right track perhaps.

 

In the render loop

internal void
Render(game_memory *Memory)
{
    game_state *GameState = (game_state *)Memory->PermanentStorage;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glm::mat4 Model = glm::mat4(1.0f);
    glm::mat4 Projection = glm::ortho(0.0f, 1280.0f, 720.0f, 0.0f, 0.0f, 1.0f);


    GLint ModelUniform = glGetUniformLocation(GameState->ShaderProgram, "Model");
    Assert(ModelUniform != -1);
    glUniformMatrix4fv(ModelUniform, 1, GL_FALSE, glm::value_ptr(Model));

    GLint ProjectionUniform = glGetUniformLocation(GameState->ShaderProgram, "Projection");
    Assert(ProjectionUniform != -1);
    glUniformMatrix4fv(ProjectionUniform, 1, GL_FALSE, glm::value_ptr(Projection));

    // I am perfectly aware allocating and unallocating new arrays each frame is slow
    // This is just test code so I can get an idea of what I am doing.
    GLuint VertexArrayObject;
    glGenVertexArrays(1, &VertexArrayObject);
    glBindVertexArray(VertexArrayObject);

    GLuint VertexBufferObject;
    glGenBuffers(1, &VertexBufferObject);

    GLfloat Point[] = 
    {
    //  Position        | Color
        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f
    };

    glBindBuffer(GL_ARRAY_BUFFER, VertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Point), Point, GL_STATIC_DRAW);

    GLuint ElementBufferObject;
    glGenBuffers(1, &ElementBufferObject);

    GLuint Elements[] = 
    {
        0
    };

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBufferObject);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Elements), Elements, GL_STATIC_DRAW);

    glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, 0);
    
    glDeleteBuffers(1, &VertexBufferObject);
    glDeleteBuffers(1, &ElementBufferObject);
    glDeleteVertexArrays(1, &VertexArrayObject);

    SDL_GL_SwapWindow(GameState->SdlWindow);
}

Code for setting the vertex properties

    // Before here is where I compile the shaders
    GLint PosAttrib = glGetAttribLocation(GameState->ShaderProgram, "position");
    glEnableVertexAttribArray(PosAttrib);
    glVertexAttribPointer(PosAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);

    GLint ColAttrib = glGetAttribLocation(GameState->ShaderProgram, "color");
    glEnableVertexAttribArray(ColAttrib);
    glVertexAttribPointer(ColAttrib , 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
    // After here is where I enter the game loop

Fragment Shader

#version 150

in vec4 Color;

void main(void)
{
    gl_FragColor = Color;
}

Vertex Shader

#version 150

in vec3 color;
in vec3 position;
out vec4 Color;
uniform mat4 Model;
uniform mat4 Projection;

void main(void)
{
    Color = vec4(color, 1.0f);
    gl_Position = Projection * Model * vec4(position, 1.0);
}

Edited by mojobojo

Share this post


Link to post
Share on other sites

You need to call glVertexAttribPointer while the buffer is bound (i.e. right after glBindBuffer).

Ah, I see, thanks. That makes sense. Moved it right after the binds however still not drawing.

 

EDIT:
Silly me, I needed to set the point size tongue.png

 

glPointSize(10.0f);

Edited by mojobojo

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!