Я новичок в OpenGL, и я следую нескольким учебникам, я заметил, что есть несколько методов, которые используются для визуализации объектов, но я все еще не понимаю разницу между ними и когда использовать каждый из них?
например .. Я слежу за этим пример который использовал шейдеры для рендеринга куба, и когда я пытался рендерить его, используя «нормальный» способ — если это правильное выражение. ничего не делается Мне всегда нужно звонить shaderProgram.setAttributeArray()
, shaderProgram.enableAttributeArray()
а также shaderProgram.disableAttributeArray()
Но если я попытался сделать это напрямую, используя другой способ — опять же, если это правильное выражение — используя glBegin()
а также glEnd()
, ничего не работает
Кроме того, у меня есть еще одна концепция шейдера для вопросов, я не очень понимаю, когда я должен ее использовать, а когда нет.
Вот мой пример:
#include "glwidget.h"
GlWidget::GlWidget(QWidget *parent)
: QGLWidget(QGLFormat(/* Additional format options */), parent)
{
alpha = 25;
beta = -25;
distance = 2.5;
}
void GlWidget::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
qglClearColor(QColor(Qt::white));
shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
shaderProgram.link();
vertices << QVector3D(-0.5, -0.5, 0.5) << QVector3D( 0.5, -0.5, 0.5) << QVector3D( 0.5, 0.5, 0.5) // Front
<< QVector3D( 0.5, 0.5, 0.5) << QVector3D(-0.5, 0.5, 0.5) << QVector3D(-0.5, -0.5, 0.5)
<< QVector3D( 0.5, -0.5, -0.5) << QVector3D(-0.5, -0.5, -0.5) << QVector3D(-0.5, 0.5, -0.5) // Back
<< QVector3D(-0.5, 0.5, -0.5) << QVector3D( 0.5, 0.5, -0.5) << QVector3D( 0.5, -0.5, -0.5)
<< QVector3D(-0.5, -0.5, -0.5) << QVector3D(-0.5, -0.5, 0.5) << QVector3D(-0.5, 0.5, 0.5) // Left
<< QVector3D(-0.5, 0.5, 0.5) << QVector3D(-0.5, 0.5, -0.5) << QVector3D(-0.5, -0.5, -0.5)
<< QVector3D( 0.5, -0.5, 0.5) << QVector3D( 0.5, -0.5, -0.5) << QVector3D( 0.5, 0.5, -0.5) // Right
<< QVector3D( 0.5, 0.5, -0.5) << QVector3D( 0.5, 0.5, 0.5) << QVector3D( 0.5, -0.5, 0.5)
<< QVector3D(-0.5, 0.5, 0.5) << QVector3D( 0.5, 0.5, 0.5) << QVector3D( 0.5, 0.5, -0.5) // Top
<< QVector3D( 0.5, 0.5, -0.5) << QVector3D(-0.5, 0.5, -0.5) << QVector3D(-0.5, 0.5, 0.5)
<< QVector3D(-0.5, -0.5, -0.5) << QVector3D( 0.5, -0.5, -0.5) << QVector3D( 0.5, -0.5, 0.5) // Bottom
<< QVector3D( 0.5, -0.5, 0.5) << QVector3D(-0.5, -0.5, 0.5) << QVector3D(-0.5, -0.5, -0.5);
}
void GlWidget::resizeGL(int width, int height)
{
if (height == 0) {
height = 1;
}
pMatrix.setToIdentity();
pMatrix.perspective(60.0, (float) width / (float) height, 0.001, 1000);
glViewport(0, 0, width, height);
}
void GlWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;
QMatrix4x4 cameraTransformation;
cameraTransformation.rotate(alpha, 0, 1, 0);
cameraTransformation.rotate(beta, 1, 0, 0);
QVector3D cameraPosition = cameraTransformation * QVector3D(0, 0, distance);
QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);
vMatrix.lookAt(cameraPosition, QVector3D(0, 0, 0), cameraUpDirection);
shaderProgram.bind();
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
// This code is able to draw the cube
shaderProgram.setAttributeArray("vertex", vertices.constData());
shaderProgram.enableAttributeArray("vertex");
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
shaderProgram.disableAttributeArray("vertex");
// end
// This code is never able to draw the cube or anything
glBegin(GL_TRIANGLES);
for (int var = 0; var < vertices.size(); ++var) {
glVertex3f(vertices[var][0],vertices[var][1],vertices[var][2]);
}
glEnd();
// end
shaderProgram.release();
}
OpenGL раньше имел то, что называетсянемедленный режим«. В нем вы бы использовали glBegin()
а также glEnd()
и между ними укажите ваши данные (точки, нормали, координаты текстуры) точка за точкой. Вы будете делать это на каждом кадре, поэтому очевидно, что это очень медленно. Эта функциональность уже давно устарела, но большинство драйверов видеокарт все еще поддерживают ее, чтобы не сломать существующее программное обеспечение. Однако, если вы хотите изучать современный OpenGL, я бы проигнорировал любой учебник, который имеет glBegin()
в этом. Сегодня вы передаете данные в GPU за один раз (во что-то Объект буфера вершины), затем рисуем одной командой (используя Vertex Array Object)
Ваш другой вопрос был о шейдерах. Опять же, в старые времена OpenGL имел трубопровод с фиксированной функцией. Это означает, что вы предоставляете только данные вершин (нормальные, …), а видеокарта работает и делает свое дело. Вы не можете изменить то, что он делает с данными. В современном мире некоторые части конвейера являются программируемыми, что означает, что вы можете изменить то, что делают некоторые части конвейера (предоставляя свои собственные программы — шейдеры). Это очень полезно, так как есть много эффектов, которые было бы невозможно достичь иначе. Опять же, если вы не предоставите свои собственные шейдеры, видеокарта в большинстве случаев будет использовать стандартную реализацию по причинам совместимости. Но вы обязательно должны написать свои собственные шейдеры (основные из них — всего лишь пара строк).
В общем, если вы начнете изучать современные OpenGL (VBO, VAO, шейдеры), вам может понадобиться немного больше времени, чтобы освоить основы, но если вы начнете изучать унаследованные вещи, однажды вам придется оставить его и начать все сначала. Изначально изучая современный OpenGL.
Изменить: Обычно не очень хорошая идея смешивать современный и устаревший код. Вы можете заставить это работать, но это просто не стоит боли.