Raph Schim
Raph Schim

Reputation: 538

Opengl 3+ draw lines with differents colors

I'm using SIFT algorithm and I want to draw lines between keypoints in differents image. I made it, but actually, all my lines have the same color so it's unreadable.
What I want to achieve is to set a random color to each line, but 1 and only 1 color to a line.

I have to use shaders to do that, and so I send LINES and POINTS (that is the color) to the same shader, and I don't know what's wrong in my code (I have a crash when trying to execute my code. EDIT : It is not that something is wrong in my code (well, obviously yes...) but the error cause a crash, like if I had a segmentation fault. So I think my errors is due to a wrong place allocation for my color array (because it worked without this array))

my code :

std::vector<GLfloat> points;
std::vector<glm::vec3> colors;
GLuint VAO, VBO[2];

void setupLines() {

    glGenVertexArrays(1, &VAO);
    glGenBuffers(2, &VBO[0]);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(GLfloat), &points[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), &colors[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);

    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}

void draw() {
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glDrawArrays(GL_LINES, 0, points.size());

    //The error occurs here, it seems...
    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glDrawArrays(GL_POINTS, 0, colors.size());

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

//for each points, we create the same colors 2by 2 so lines (that are 2 points) have the same colors
void addColor() {
    for (int i = 0; i < points.size()/2; ++i) {
        float a = rand() / (float)RAND_MAX;
        float b = rand() / (float)RAND_MAX;
        float c = rand() / (float)RAND_MAX;
        colors.push_back(glm::vec3(a, b, c));
        colors.push_back(glm::vec3(a, b, c));
    }
}

and my vertex Shader :

#version 330 core
layout (location = 0) in vec2 aTexCoord;
layout (location = 1) in vec3 color;
out vec2 TexCoord;
out vec3 Col;

void main()
{
    TexCoord = vec2(aTexCoord.xy);
    Col = color;
}

and then I use Col in fragment shader to color.
Is it how I have to do this?

Upvotes: 3

Views: 8031

Answers (1)

Rabbid76
Rabbid76

Reputation: 210878

You have to set the current position gl_Position in the vertex shader.

The vertex coordinate has to be an attribute:

in vec3 aVertCoord;

and you have to assigne the coordinate to gl_Position:

gl_Position = vec4(aVertCoord.xyz, 1.0);

Note, for 2D coordinates it is should be something like:

in vec2 aVertCoord;

void main()
{
    .....
    gl_Position = vec4(aVertCoord.xy, 0.0, 1.0);
}

In final you have 2 vertex attributes. The vertex coordinates and the color. You do not need any texture coordinates, because you draw lines (GL_LINES).
But I guess what you call aTexCoord is the vertex position, so you have to do it like this:

#version 330 core
layout (location = 0) in vec2 aTexCoord;
layout (location = 1) in vec3 color;

out vec3 TexCoord;
out vec3 Col;

void main()
{
    gl_Position = vec4(aTexCoord.xy, 0.0, 1.0);
    TexCoord    = aTexCoord.xy;
    Col         = color;
} 

The vertex array object VAO stores the states of the generic vertex attributes (glVertexAttribPointer, glEnableVertexAttribArray). The vertex attribute state may refer to a vertex array buffer. You have to bind the vertex array object VAO only, when you draw the object (lines):

void draw() {
    glBindVertexArray(VAO);
    int numberOfPoints = points.size() / 2; // Number of points, not the number of floats
    glDrawArrays(GL_LINES, 0, numberOfPoints ); 
    glBindVertexArray(0);
}

Note, it sufficient to call glDrawArrays one time.


Further, the 1st paramter of glVertexAttribPointer is the attribute index:

glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), &colors[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(
    1, // <---------------------------- attribute index
    3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); 


Since you need one color per vertex coordinate, but you want every line to be drawn in a single color, you have to do it like this:

void addColor()
{
    int numberOfPoints = points.size() / 2;
    for (int i = 0; i < numberOfPoints/2; ++i)
    {
        glm::vec3 col(
            rand() / (float)RAND_MAX,
            rand() / (float)RAND_MAX,
            rand() / (float)RAND_MAX);
        colors.push_back(col);
        colors.push_back(col);
    }
}

Upvotes: 4

Related Questions