OpenGL:多种渲染方法.. 何时使用哪个?
Posted
技术标签:
【中文标题】OpenGL:多种渲染方法.. 何时使用哪个?【英文标题】:OpenGL: Multiple Rending methods .. When to use which? 【发布时间】:2015-01-12 21:06:53 【问题描述】:我是 OpenGL 的新手,我正在学习多个教程,我注意到有多种方法用于渲染对象,但我仍然不明白它们之间的区别以及何时使用它们?
例如 .. 我正在关注使用着色器渲染立方体的 example,当我尝试使用“正常”方式渲染它时 - 如果这是一个正确的表达式。什么都没有被渲染。我总是需要打电话给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();
【问题讨论】:
【参考方案1】:OpenGL 曾经有所谓的“immediate mode”。在其中,您将使用glBegin()
和glEnd()
,并在它们之间逐点指定您的数据(点、法线、纹理坐标)。你会在每一帧上都这样做,所以显然这很慢。此功能早已被弃用,但大多数显卡驱动程序仍然支持它,以免破坏现有软件。但是,如果您想学习现代 OpenGL,我会忽略任何包含 glBegin()
的教程。今天,您一次性将数据传输到 GPU(到称为 Vertex Buffer Object 的东西),然后用一个命令绘制(使用 Vertex Array Object)
您的另一个问题是关于着色器的。同样,在过去,OpenGL 曾经有一个fixed-function pipeline。这意味着您只提供顶点(正常,...)数据,而显卡会继续执行它的工作。您无法修改它对数据的作用。在现代世界中,管道的某些部分是可编程的,这意味着您可以更改管道的某些部分的功能(通过提供您自己的程序 - shaders)。这非常有用,因为有许多其他方式无法实现的效果。同样,如果您不提供自己的着色器,出于兼容性原因,显卡大多会退回到默认实现。但是您绝对应该编写自己的着色器(基本的只是几行代码)。
总而言之,如果您开始学习现代 OpenGL(VBO、VAO、着色器),可能需要更长的时间来完成基础知识,但如果您开始学习遗留的东西,总有一天您将不得不离开它并从头开始学习现代 OpenGL。
编辑:混合现代和遗留代码通常不是一个好主意。你可能会得到它的工作,但它只是不值得痛苦。
【讨论】:
但我有一个问题......在最后一个例子中,这家伙到底在哪里使用 VertexBufferObject 和 VertexArrayObject? 此外,此示例仅显示如何使用调用glDrawArrays(GL_TRIANGLES, 0, vertices.size());
渲染三角形,但如果我想渲染例如 Normals
.. 使用 shaders
模式可以替代什么? .. 即,glNormal3d()
呼叫的替代方案是什么?
在示例中,作者没有使用VBO和VAO,而是使用glDrawArrays,在渲染之前将数据从内存一次性复制到OpenGL。它介于即时模式和 VBO 之间(今天也已弃用)。您找到的示例是,我想较少解释一般的 OpenGL,而更多地考虑 Qt OpenGL 库。
你不渲染法线。您像顶点一样传递它们(每个顶点都应该有一个法线),然后将它们全部渲染。法线用于照明,所以我建议阅读“照明”一章,其中可能有一些解释。
我不知道很多教程网站,但opengl-tutorial.org 看起来不错 - 你可以看看。以上是关于OpenGL:多种渲染方法.. 何时使用哪个?的主要内容,如果未能解决你的问题,请参考以下文章
使用 opencl 将软件渲染到 opengl 2d 视图 [关闭]