OpenGL 3+绘制不同颜色的线条

3
我正在使用SIFT算法,并希望在不同的图像关键点之间画线。我已经实现了这一点,但是所有的线都是同样的颜色,因此不可读。
我想要实现的是为每条线设置随机颜色,但是每条线只有1个颜色。
我必须使用着色器来完成这个操作,所以我将LINES和POINTS(即颜色)发送到同一个着色器中,但是我不知道我的代码有什么问题(当我尝试执行我的代码时会崩溃。编辑:不是我的代码出了问题(显然是...),而是错误导致了崩溃,就像我有一个分段错误一样。所以我认为我的错误是由于我的颜色数组分配位置错误引起的(因为没有这个数组也可以工作))
我的代码:
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));
    }
}

我的顶点着色器:

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

然后我在片元着色器中使用Col来进行颜色处理。
这样做是正确的吗?


1
因为points是一个std::vector<GLfloat>,而colors是一个std::vector<glm::vec3>,它们的大小相同。但也许这是错误的... - Raph Schim
1个回答

4

您需要在顶点着色器中设置当前位置gl_Position

顶点坐标必须是一个属性:

in vec3 aVertCoord;

你需要将坐标分配给gl_Position

gl_Position = vec4(aVertCoord.xyz, 1.0);

注意,对于二维坐标应该是这样的:
in vec2 aVertCoord;

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

最终你有两个顶点属性。顶点坐标和颜色。你不需要任何纹理坐标,因为你绘制的是线(`GL_LINES`)。但我猜你所说的`aTexCoord`是顶点位置,所以你需要这样做:
#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;
} 

顶点数组对象VAO存储着通用顶点属性(glVertexAttribPointer, glEnableVertexAttribArray)的状态。顶点属性的状态可能会涉及到一个顶点数组缓冲区。只有在绘制物体(线条)时,你才需要绑定顶点数组对象VAO

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

注意,只需要调用glDrawArrays一次即可。


此外,glVertexAttribPointer的第一个参数是属性索引:

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

由于每个顶点坐标需要一个颜色,但你希望每条线都用同一种颜色绘制,因此你需要像这样做:
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);
    }
}

我仍然遇到崩溃问题。 奇怪的是,当我删除 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); 这一部分时,崩溃就不会发生了。 - Raph Schim
再次感谢,我看到了这个错误并将points.size()/2更改为points.size()/4。这意味着我实际上有很多颜色。 当我调用glDrawArrays时,我的错误是“尝试在0x0000000000位置获取某些内容”。 哦!也许这是因为glm::vec3不仅仅是3个浮点数,而是更多? /: - Raph Schim
我太...蠢了!真的!非常感谢您...我太专注于错误可能无处不在这个事实,以至于我没有看到这个拼写错误... 非常感谢! 感谢您给我的所有建议! - Raph Schim
但是,最后一件事!由于我需要我的线条颜色相同,所以我的线条的2个点必须具有相同的颜色,因此我必须使用2次 colors.push_back(glm::vec3(a,b,c));,这样它就具有2个连续点的相同值! - Raph Schim
1
准确无误! :) ^^ - Raph Schim
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接