QtOpenGLWidget рисующий треугольник - PullRequest
0 голосов
/ 24 августа 2018

Как я могу изменить следующий код так, чтобы он фактически рисовал треугольник?

Сначала идет шейдер, затем реализация класса glwiedget, который получен из 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 Ответ

0 голосов
/ 25 августа 2018

Вы должны определить индекс атрибута posAttr после того, как программа связана:

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

Поскольку проверка глубины включена, необходимо очистить буфер глубины.См. glClear:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Вы не используете какую-либо модель, вид или матрицу проекции, поэтому координаты должны быть установлены в нормализованном пространстве устройства.Это означает, что все координаты должны находиться в диапазоне [-1,0, 1,0], особенно следует учитывать ближнюю и дальнюю плоскости -1,0 и 1,0.По умолчанию функция проверки глубины равна GL_LESS, поэтому полоса отсечения ограничивается дальней плоскостью, поскольку координата z в 1,0 равна не меньше, чем в дальней плоскости 1,0.Используйте z координату 0,0 для вершин (конечно, что-то вроде 0,99 тоже будет работать):

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

3D-параметр glDrawArrays должен быть числом вершина не количество примитивов:

 glDrawArrays(GL_TRIANGLES, 0, 3);

Соответствующие части кода могут выглядеть следующим образом:

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

Обратите внимание, поскольку Выбор лица включен, у вас естьсоблюдать порядок намотки примитивов (это так, в вашем коде).


Кроме того, как упоминалось @derhass, в комментариях вы должны изменить фрагментный шейдер.Вы должны определить Выходную переменную .(Примечание: используйте Необработанные строковые литералы ):

static const char* fragmentShaderSource = R"(
    #version 330 core

    out vec4 fragColor;

    void main() {
        fragColor = vec4(1.0, 0.0, 1.0, 0.0);
    }
)";

Предварительный просмотр:

polygon


Если вы хотите рисовать линии вместо полигонов, то вы можете сделать это с помощью GL_LINE_LOOP.См. Линейные примитивы .

glDrawArrays(GL_LINE_LOOP, 0, 3);

lines

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...