Opengl 3+用不同颜色绘制线条

Posted

技术标签:

【中文标题】Opengl 3+用不同颜色绘制线条【英文标题】:Opengl 3+ draw lines with differents colors 【发布时间】:2018-01-04 13:08:41 【问题描述】:

我正在使用 SIFT 算法,我想在不同图像的关键点之间画线。我做到了,但实际上,我所有的线条都有相同的颜色,所以不可读。 我想要实现的是为每条线设置一个随机颜色,但一条线只有一种颜色。

我必须使用着色器来执行此操作,因此我将 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 进行着色。 我必须这样做吗?

【问题讨论】:

好吧,因为 points 是 std::vector&lt;GLfloat&gt; 而 colors 是 std::vector&lt;glm::vec3&gt; 并且它们具有相同的大小。但也许这是错误的...... 【参考方案1】:

您必须在顶点着色器中设置当前位置gl_Position

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

in vec3 aVertCoord;

你必须将坐标分配给gl_Position

gl_Position = vec4(aVertCoord.xyz, 1.0);

注意,对于 2D 坐标,它应该是这样的:

in vec2 aVertCoord;

void main()

    .....
    gl_Position = vec4(aVertCoord.xy, 0.0, 1.0);

最终你有 2 个顶点属性。顶点坐标和颜色。你不需要任何纹理坐标,因为你画线(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存储通用顶点属性的状态(glVertexAttribPointerglEnableVertexAttribArray)。顶点属性状态可以指顶点数组缓冲区。绘制对象(线)时,您只需绑定顶点数组对象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), &amp;colors[0], GL_STATIC_DRAW); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); 部分时不会发生崩溃 再次感谢,我看到了这个错误并将 points.size()/2 更改为 points.size()/4。这意味着我实际上有很多颜色。当我调用 glDrawArrays 时,我的错误是“试图在 0x0000000000 处取东西”。哦哦!也许那是因为 glm::vec3 不仅仅是 3 float 而是更多? /: 我……笨!呸!非常感谢...我非常专注于错误无处不在的事实,以至于我没有看到这个错字...非常感谢!并感谢您给我的所有提示! 没错! :) ^^

以上是关于Opengl 3+用不同颜色绘制线条的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 3.0 Java绘制带有颜色数组的顶点(每个顶点的颜色不同)

用Bresenham线算法绘制线条

在 OpenGL 3+ 中有效地绘制多边形(每个多边形一种颜色)

OpenGL:使用退化三角形绘制线

在 OpenGL 中绘制 2D 形状的轮廓,同时更改线条粗细

OpenGL基础篇——使用面向对象方法封装OpenGL函数