一、绘制甜甜圈
核心代码
//void gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
//参数1:GLTriangleBatch 容器帮助类
//参数2:外边缘半径
//参数3:内边缘半径
//参数4、5:主半径和从半径的细分单元数量
gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);
使用默认函数gltMakeTorus,初始化一个torusBatch批次类用来进行绘制。
绘制结果
但是进行旋转后,出现了渲染bug
二、油画算法
按照图层添加的顺序,依次进行绘制。重合的部分,会被后面绘制的片元信息覆盖。
缺点:
- 会对重叠的片元进行多次写操作,速度慢。
- 对于独立的三角形进行排序,开销过高。
- 如果三个三角形,两两叠加,就无法处理。如下图所示
甜甜圈出现的问题
三、油画算法解析甜甜圈
图片来源:康奈尔大学:计算机图形学入门
为了看清楚构造,为我们设置多边形填充模式为线填充。
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
初始化的甜甜圈
如上图所示,甜甜圈的顶点数据所指代的三角形,是从内环到外环排列一圈后,然后绘制下一圈,最后绘制的一圈和最开始绘制的接在一起。 且一圈中,排列起点是内环中间,经过外环,旋转布局一圈后,再次回到内环中间。
如上图所示,红色表示靠近观察者的一面,黑色是和红色三角形平行的,且远离观察者的一面。
由于同一个环中,远离观察者的一面先绘制,因此后绘制的内容会修改重叠部分片元信息,最终呈现的是靠近用户侧的颜色。
此时,如果使用默认光源,靠近用户侧的一侧,会渲染成红色,而远离用户侧的会渲染成黑色。
两个因素叠加,颜色正常显示。
旋转后的甜甜圈
上半部分
黑1渲染 -> 红1渲染 -> 黑2渲染 -> 红2渲染 -> 黑3渲染 -> 红3渲染
此时:
黑1 的右半部分,被后渲染的 红1 覆盖。
红1 的后半部分,被后渲染的 黑2 覆盖。
黑2 的后半部分,被后渲染的 红2 覆盖。
...
下半部分
如上图所示,解释了为什么甜甜圈颜色开始错乱的时候,总是错一半。
由于甜甜圈是围成的一个环,所以上下两部分或者左右两部分,绘制的方向是相反的。
黑1渲染 -> 红1渲染 -> 黑2渲染 -> 红2渲染 -> 黑3渲染 -> 红3渲染
此时:
黑1 被后渲染的 红1 和 红2 覆盖。
黑2 被后渲染的 红2 和 红3 覆盖。
...
四、OpenGL 表面剔除算法
OpenGL 对三角形的旋转方向进行定义。
面对观察者的方向为正面,把正面的三角形旋转方向定义为正,则与此旋转方向相反的三角形都是背面。
默认逆时针旋转三角形为正面。
图片来源: LearnOpenGL-CN
在甜甜圈案例中,虽然我们设置的三角形都是逆时针旋转的,但是由于表面发生了折叠,远离观察者的一面,开起来就是逆时针旋转了,就变成了背面。
如果我们开启了 背面剔除,此时黑色部分,即远离观察者的一面不会被渲染,也就不再出现错乱的现象。
五、表面面剔除参数解析
开启表面剔除(默认剔除背面)
glEnable(GL_CULL_FACE);
关闭表面剔除
glDisable(GL_CULL_FACE);
用户选择剔除哪个面,正面/背面/全部
GL_FRONT, GL_BACK, GL_FRONT_AND_BACK , 默认GL_BACK
glCullFace(GL_FRONT);
用户指定绕序哪个为正面。默认逆时针三角形为正面
GL_CW,GL_CCW 逆时针/顺时针
glFrontFace(GL_CW);