首先你应该知道,OpenGL 是一个状态机。这意味着,除了创建 OpenGL 上下文(由 SFML 完成)之外,没有初始化之类的东西!
因为我不太擅长通过记忆来学习东西,
这个不错……</p>
我总是需要回答“我们为什么要这样做?”
这太棒了!
在开始用 glBegin() 和 glEnd() 绘制东西之前,请有人向我解释一下我必须对 OpenGL 定义什么(只有纯 OpenGL,我使用 SFML 作为背景库,但这并不重要)?
正如我已经说过的:OpenGL 是一个状态机。这基本上意味着,您可以执行两种调用:设置状态和执行操作。
例如glClearColor
,设置一个状态变量,即清除颜色的状态变量,该值用于在glClear
设置GL_COLOR_BUFFER_BIT
标志的调用时清除活动帧缓冲区颜色。glClearDepth
深度值(GL_DEPTH_BUFFER_BIT
flag to glClear
)存在类似的函数。
glBegin
glEnd
属于OpenGL的即时模式,已被弃用。所以学习它们没有什么理由。您应该改用顶点数组,最好通过顶点缓冲区对象。
但这里是这样:glBegin
将 OpenGL 设置为现在应该绘制几何图形的状态,该几何图形被选为glBegin
. GL_TRIANGLES
例如意味着,OpenGL 现在将每 3 次调用解释glVertex
为形成一个三角形。glEnd
告诉 OpenGL 你已经完成了那批三角形。在 glBegin...glEnd 块中,某些状态更改是不允许的。其中包括与转换几何和生成图片有关的所有内容,包括矩阵、着色器、纹理等。
一种常见的误解是,OpenGL 已初始化。这是由于具有initGL
功能或类似功能的教程编写得不好。在开始渲染场景时从头开始设置所有状态是一个很好的做法。但是由于单个帧可能包含多个场景(想想 HUD 或分屏游戏),这种情况会在一个场景中发生多次。
更新:
那么如何画三角形呢?好吧,这很简单。首先,您需要几何数据。例如这个:
GLfloat triangle[] = {
-1, 0, 0,
+1, 0, 0,
0, 1, 0
};
在渲染函数中,我们告诉 OpenGL 下一次调用 glDrawArrays 或 glDrawElements 应该从那里获取数据(为了简单起见,我将在这里使用 OpenGL-2 函数):
glVertexPointer(3, /* there are three scalars per vertex element */
GL_FLOAT, /* element scalars are float */
0, /* elements are tightly packed (could as well be sizeof(GLfloat)*3 */
trignale /* and there you find the data */ );
/* Note that glVertexPointer does not make a copy of the data!
If using a VBO the data is copied when calling glBufferData. */
/* this switches OpenGL into a state that it will
actually access data at the place we pointed it
to with glVertexPointer */
glEnableClientState(GL_VERTEX_ARRAY);
/* glDrawArrays takes data from the supplied arrays and draws them
as if they were submitted sequentially in a for loop to immediate
mode functions. Has some valid applications. Better use index
based drawing for models with a lot of shared vertices. */
glDrawArrays(Gl_TRIANGLE, /* draw triangles */
0, /* start at index 0 */
3, /* process 3 elements (of 3 scalars each) */ );
我还没有包括设置转换和视口映射。
视口定义了易于投影和标准化的几何图形如何放置在窗口中。此状态使用 设置glViewport(pos_left, pos_bottom, width, height)
。
今天的转换发生在顶点着色器中,本质上顶点着色器是一个用特殊语言(GLSL)编写的小程序,它获取顶点属性并计算结果顶点的剪辑空间位置。通常的方法是模拟固定函数管道,这是一个两阶段的过程:首先将几何体转换到视图空间(一些计算,如照明在这个空间中更容易),然后将其投影到剪辑空间,这是一种渲染器的镜头。在固定函数管道中,有两个转换矩阵:Modelview 和 Projection。您将它们设置为所需结果所需的任何值。在只有三角形的情况下,我们保留模型视图标识并在任一维度上使用从 -1 到 1 的正交投影。
glMatrixMode(GL_PROJECTION);
/* the following function multiplies onto what's already on the stack,
so reset it to identity */
glLoadIdentity();
/* our clip volume is defined by 6 orthogonal planes with normals X,Y,Z
and ditance 1 from origin into each direction */
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
/* now a identity matrix is loaded onto the modelview */
glLoadIdentity();
设置好转换后,我们现在可以绘制上述三角形:
draw_triangle();
最后我们需要告诉 OpenGL 我们已经完成了发送命令,它应该完成它的渲染。
if(singlebuffered)
glFinish();
然而大多数时候你的窗口是双缓冲的,所以你需要交换它以使事情变得更生动。由于没有完成交换就没有意义,因此交换意味着完成
else
SwapBuffers();