QtOpenGLWidget 绘制三角形 [英] QtOpenGLWidget drawing triangle

查看:67
本文介绍了QtOpenGLWidget 绘制三角形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何更改以下代码以使其实际绘制三角形?

首先是着色器,然后是从 QOpenglWidget 派生的 glwiedget 类的实现.

//这里的着色器静态常量字符* vertexShaderSource ="#version 330 核心\n""在 vec3 posAttr;\n"//"属性lowp vec3 colAttr;\n"//"不同的lowp vec4 col;\n"//"统一highp mat4矩阵;\n""void main() {\n"//" col = colAttr;\n"" gl_Position = vec4(posAttr, 1) ;\n""}\n";//片段着色器静态常量字符* fragmentShaderSource ="#version 330 核心\n"//"不同的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(){清理(​​);}void Glwidget::initializeGL(){connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &Glwidget::cleanup);初始化OpenGLFunctions();glClearColor(.0f, .0f, .0f, 1.0f);着色器 = 新的 QOpenGLShaderProgram(this);着色器-> addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);着色器-> addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);//posAttribute = shader->attributeLocation("posAttr");//colAttribute = shader->attributeLocation("colAttr");//matrixAttribute = shader->uniformLocation("matrix");Q_ASSERT(着色器->链接());Q_ASSERT(shader->bind());//着色器->释放();glEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);}void Glwidget::paintGL(){glClear(GL_COLOR_BUFFER_BIT);makeCurrent();矩阵.透视(60.0, 4.0f/3.0f, 0.1f, 10.0f);矩阵.translate(0, 0, -2);matrix.rotate(100.0f, 0, 1, 0);//着色器->setUniformValue(matrixAttribute, matrix);//着色器->bind();GLfloat 顶点[] = {0.0f、0.707f、1.0f、-0.5f, -0.5f, 1.0f,0.5f、-0.5f、1.0f};着色器-> setAttributeArray(posAttribute,vertices, 3);GLfloat 颜色[] = {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, 颜色);glEnableVertexAttribArray(posAttribute);//glEnableVertexAttribArray(colAttribute);glDrawArrays(GL_TRIANGLES, 0, 1);glDisableVertexAttribArray(posAttribute);//glDisableVertexAttribArray(colAttribute);//着色器->释放();}void Glwidget::resizeGL(int w, int h){矩阵.setToIdentity();matrix.perspective(45.0f, w/float(h), 0.01f, 1000.0f);//glViewport(0, 0, w, h);}void Glwidget::mousePressEvent(QMouseEvent *event){Q_UNUSED(事件);}void Glwidget::mouseMoveEvent(QMouseEvent *event){Q_UNUSED(事件);}void Glwidget::cleanup(){如果(着色器 == nullptr)返回;makeCurrent();删除着色器;着色器 = 0;doneCurrent();}

解决方案

你要确定posAttr的属性索引,程序链接后:

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

由于启用了深度测试,您必须清除深度缓冲区.请参阅

<小时>

如果你想画线而不是多边形,那么你可以通过GL_LINE_LOOP来完成.请参阅

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

解决方案

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 绘制三角形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆