QtOpenGLWidget drawing triangle

匿名 (未验证) 提交于 2019-12-03 01:36:02

问题:

How can I change the following code so that it actually draws the triangle?

First is the shader, then the implementation of the glwiedget class which is derived from QOpenglWidget.

// shaders here       static const char* vertexShaderSource =         "#version 330 core\n"         "in vec3 posAttr;\n"         //"attribute lowp vec3 colAttr;\n"         //"varying lowp vec4 col;\n"         //"uniform highp mat4 matrix;\n"         "void main() {\n"         //"   col = colAttr;\n"         "   gl_Position = vec4(posAttr, 1) ;\n"         "}\n"; // fragment shader     static const char* fragmentShaderSource =         "#version 330 core\n"         //"varying lowp vec4 col;\n"         "void main() {\n"         "gl_FragColor = vec4(1.0, 0.0, 1.0, 0.0);\n"         "}\n";   Glwidget::Glwidget(QWidget* parent):QOpenGLWidget(parent) {  // }  Glwidget::~Glwidget() {     cleanup(); }  void Glwidget::initializeGL() {     connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &Glwidget::cleanup);      initializeOpenGLFunctions();     glClearColor(.0f, .0f, .0f, 1.0f);     shader = new QOpenGLShaderProgram(this);      shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);     shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource); //    posAttribute = shader->attributeLocation("posAttr");     //colAttribute = shader->attributeLocation("colAttr");     //matrixAttribute = shader->uniformLocation("matrix");       Q_ASSERT(shader->link());     Q_ASSERT(shader->bind());     //shader->release();     glEnable(GL_DEPTH_TEST);     glEnable(GL_CULL_FACE); } void Glwidget::paintGL() {     glClear(GL_COLOR_BUFFER_BIT);     makeCurrent();     matrix.perspective(60.0, 4.0f/3.0f, 0.1f, 10.0f);     matrix.translate(0, 0, -2);     matrix.rotate(100.0f, 0, 1, 0);     //shader->setUniformValue(matrixAttribute, matrix);  //    shader->bind();     GLfloat vertices[] = {         0.0f, 0.707f, 1.0f,         -0.5f, -0.5f, 1.0f,         0.5f, -0.5f, 1.0f     };     shader->setAttributeArray(posAttribute,vertices, 3);      GLfloat colors[] = {         1.0f, 0.0f, 0.0f,         0.0f, 1.0f, 0.0f,         0.0f, 0.0f, 1.0f     };       glVertexAttribPointer(posAttribute, 3, GL_FLOAT, GL_FALSE, 0, vertices);      //glVertexAttribPointer(colAttribute, 3, GL_FLOAT, GL_FALSE, 0, colors);       glEnableVertexAttribArray(posAttribute);      //glEnableVertexAttribArray(colAttribute);       glDrawArrays(GL_TRIANGLES, 0, 1);       glDisableVertexAttribArray(posAttribute);      //glDisableVertexAttribArray(colAttribute);      //shader->release(); }  void Glwidget::resizeGL(int w, int h) {     matrix.setToIdentity();     matrix.perspective(45.0f, w / float(h), 0.01f, 1000.0f);     //glViewport(0, 0, w, h); }  void Glwidget::mousePressEvent(QMouseEvent *event) {     Q_UNUSED(event); }  void Glwidget::mouseMoveEvent(QMouseEvent *event) {     Q_UNUSED(event); }  void Glwidget::cleanup() {     if (shader == nullptr)         return;     makeCurrent();      delete shader;     shader = 0;     doneCurrent(); }

回答1:

You have to determine the attribute index of posAttr, after the program is linked:

Q_ASSERT(shader->link()); posAttribute = shader->attributeLocation("posAttr");

Since the depth test is enabled, you have to clear the depth buffer. See glClear:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

You do not use any model, view or projection matrix, so the coordinates have to be set in normalized device space. This means all the coordinates have to be in the range [-1.0, 1.0], especially the near plane and far plane of -1.0 and 1.0 have to be considered. By default the depth test function is GL_LESS, so you tringle is clipped by the far plane, because a z coordinate of 1.0 is not less than the far plane of 1.0. Use a z coordinate of 0.0, for the vertices (of course somthing like 0.99 would work, too):

GLfloat vertices[] = { 0.0f, 0.707f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f }; shader->setAttributeArray(posAttribute,vertices, 3);    

The 3d paramter of glDrawArrays has to be the number of vertices and not the number of primitives:

 glDrawArrays(GL_TRIANGLES, 0, 3);

The relevant code parts may look like this:

void Glwidget::initializeGL() {     connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &Glwidget::cleanup);      initializeOpenGLFunctions();     glClearColor(.0f, .0f, .0f, 1.0f);     shader = new QOpenGLShaderProgram(this);      shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);     shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);      Q_ASSERT(shader->link());     posAttribute = shader->attributeLocation("posAttr");      Q_ASSERT(shader->bind());      glEnable(GL_DEPTH_TEST);     glEnable(GL_CULL_FACE); }  void Glwidget::paintGL() {      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);       GLfloat vertices[] = { 0.0f, 0.707f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f };      shader->setAttributeArray(posAttribute,vertices, 3);       glEnableVertexAttribArray(posAttribute);      glDrawArrays(GL_TRIANGLES, 0, 3);      glDisableVertexAttribArray(posAttribute); }

Note, since Face Culling is enabled, you have to respect the winding order of the primitives (this is the case, in your code).


Furthermore, as mentioned by @derhass, in the comments, you have to change the fragment shader. You have to define an Output Variable.
(Side note, use Raw string literals):

static const char* fragmentShaderSource = R"(     #version 330 core      out vec4 fragColor;      void main() {         fragColor = vec4(1.0, 0.0, 1.0, 0.0);     } )";

See the preview:


If you want to draw lines instead of polygons, then you can do this by GL_LINE_LOOP. See Line primitives.

glDrawArrays(GL_LINE_LOOP, 0, 3);



转载请标明出处:QtOpenGLWidget drawing triangle
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!