使用坐标数组在 QOpenGLWidget 中绘制 GL_LINE

Draw GL_LINE in QOpenGLWidget using array of coordinates

我已经使用 QtCreator 完成了工作应用程序。我的渲染 class 是

GLRendWindow::GLRendWindow(QWidget *parent): QOpenGLWidget(parent)

现在我想使用带有顶点坐标的数组来绘制对象。
我在这个页面上找到了一些绘制三角形的教程: OpenGL Window Example

我试着重复使用它来画简单的线

void GLRendWindow::drawLine()
{
    GLfloat line[] =
    {
        0.5f, 1.0f,
        0.5f, -1.0f
    };
    GLfloat line_colors[] =
    {
        1.0f, 0.0f, 0.0f, // red
        0.0f, 0.0f, 1.0f, // blue
    };
    shaderProgram->bind();
    glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, 0, line);
    glVertexAttribPointer(colAttr, 3, GL_FLOAT, GL_FALSE, 0, line_colors);
    glEnableVertexAttribArray(colAttr);
    glEnableVertexAttribArray(posAttr);
    glDrawArrays(GL_LINE, 0, 2);
    glDisableVertexAttribArray(posAttr);
    glDisableVertexAttribArray(colAttr);
    shaderProgram->release();
}

也是我的初始化方法

void GLRendWindow::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );

    shaderProgram = new QOpenGLShaderProgram(this);
    shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    shaderProgram->link();
    posAttr = shaderProgram->attributeLocation("posAttr");
    colAttr = shaderProgram->attributeLocation("colAttr");
}

和绘制方法

void GLRendWindow::paintGL()
{
    glClear( GL_COLOR_BUFFER_BIT );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    drawLine();

    if (isUpdated)
    {
       //some other stuff

        isUpdated = false;
    }
    glFlush();
}

和调整大小方法

void GLRendWindow::resizeGL(int w, int h)
{
    glViewport( 0, 0, w, h );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    if ( w < h && w > 0 )
    {
        glFrustum( - 1.0, 1.0, - 1.0 * h / w, 1.0 * h / w, 1.0, 5.0 );
    }
    else
    {
        if ( w >= h && h > 0 )
        {
            glFrustum( - 0.3 * w / h, 0.3 * w / h, - 0.3, 0.3, 0.5, 5.0 );
        }
    }
}

但是当我运行应用程序时,没有绘制任何东西。没有错误,没有异常,什么都没有。 在本教程中,我看到

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix * posAttr;\n"
    "}\n";

static const char *fragmentShaderSource =
    "varying lowp vec4 col;\n"
    "void main() {\n"
    "   gl_FragColor = col;\n"
    "}\n";

这里可能隐藏了解决方案,但我完全不明白它是什么以及这里发生了什么。我什至不确定这是否是绘制简单线条所必需的。
我应该怎么做才能使用坐标数组看到直线?

您错过了为颜色属性设置指定通用顶点属性数据的数组 (attribute lowp vec4 colAttr;)。这类似于指定顶点属性。
例如,将以下代码添加到 GLRendWindow::drawLine:

GLfloat line_colors[] =
{
    1.0f, 0.0f, 0.0f, // red
    0.0f, 0.0f, 1.0f  // blue
};
glVertexAttribPointer(colAttr, 3, GL_FLOAT, GL_FALSE, 0, line_colors);
glEnableVertexAttribArray(colAttr);

您没有指定颜色属性数组,所以colAttr的值默认为(0, 0, 0)。其实你是在黑底上画一条黑线。


您正在混合不同的技术。您有一个带有矩阵 Uniform:

的着色器程序
uniform highp mat4 matrix;\n"
void main() {
   // [...]

   gl_Position = matrix * posAttr;
}

你根本就没有设置这身制服。相反,您尝试设置遗留的 OpenGL 固定函数矩阵。遗留电流矩阵的​​内容并没有神奇地出现在单一变量中。

使用setUniformValue设置矩阵uniform的值:

QMatrix4x4 matrix;
int matrix_location = shaderprogram->uniformLocation("matrix");

matrix.setToIdentity();
shaderprogram->setUniformValue(matrix_location, matrix);

问题也出在这里

glDrawArrays(GL_LINE, 0, 2);

应该是

glDrawArrays(GL_LINES, 0, 2);

我不得不改变

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix * posAttr;\n"
    "}\n";

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = posAttr;\n"
    "}\n";