面剔除:只绘制面向用户的面,背对用户的面进行丢弃。
OpenGL可以检查所有面向观察者的面,并渲染它们,而丢弃那些背向的面,节约片段着色器调用。用的是:顶点数据的环绕顺序
默认情况下,逆时针顶点所定义的三角形将会被处理为正向三角形。而且实际的环绕顺序是在光栅化阶段进行的,也就是顶点着色器运行之后,
这些顶点就是从观察者视角所见的了。则顺时针的1-2-3所形成的三角形是不可见面。这个功能默认是禁用的。
当然需要更新顶点数据,用逆时针环绕的顺序定义。启用面剔除方法如下:
glEnable(GL_CULL_FACE);
之后的代码实现中,所有的背向面都会被丢弃,只对类似立方体这样的封闭形状有效。
当然也可以只剔除正向面,而不是背向面:glCullFace(GL_FRONT);
有三个参数选项:
GL_BACK————只剔除背向面
GL_FRONT————只剔除正向面
GL_FRONT_AND_BAKC————剔除背向面和正向面
默认值是GL_BACK
也可以调用glFrontFace,来调整:顺时针的面定义为正向面
glFrontFace(GL_CCW);
默认值是GL_CCW————逆时针;GL_CW————顺时针。
下面看下帧缓冲相关内容:
前面看的都是屏幕缓冲,比如:颜色缓冲,深度缓冲,模板缓冲。
把上述的缓冲结合起来就叫做帧缓冲,被存储在内存中。允许定义自己的帧缓冲,也就是可以定义自己的颜色缓冲,深度缓冲和模板缓冲
默认的帧缓冲是创建窗口的时候就生成和配置的,GLFW做好了这些。
使用函数glGenFramebuffers创建一个帧缓冲对象:
unsigned int fbo;
glGenFramebuffers(1, &fbo);
再绑定为激活的帧缓冲:
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
绑定后,所有的读取和写入帧缓冲都会影响当前绑定的帧缓冲。也可以使用GL_READ_FRAMEBUFFER或GL_DRAW_FRAMEBUFFER,把帧缓冲分别绑定到读取或写入目标
补充:
GL_READ_FRAMEBUFFER的帧缓冲将会使用在所有像是glReadPixels的读取操作中,而绑定到GL_DRAW_FRAMEBUFFER的帧缓冲将会被用作渲染、清除等写入操作的目标。
大部分情况你都不需要区分它们,通常都会使用GL_FRAMEBUFFER,绑定到两个上。
一个完整的帧缓冲需要四个条件:
1.附加至少一个缓冲(颜色,深度,模板)
2.至少有一个颜色附件
3.所有的附件必须完整(保留内存)
4.每个缓冲都应该有相同的样本数
则,下面需要对帧缓冲创建一些附件,把附件附加到帧缓冲上。完成上述四个条件后,可以调用glCheckFramebufferStatus函数,用GL_FRAMEBUFFER为参数,
检查帧缓冲是否完整。如果返回值是GL_FRAMEBUFFER_COMPLETE,则帧缓冲是完整的。
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
之后,所有的渲染操作将会渲染到当前绑定帧缓冲的附件中。但是,当前帧缓冲不是默认帧缓冲,渲染指令不会对窗口的视觉输出有啥影响。
由此可以得到一个新的概念:渲染到一个不同的帧缓冲被叫做 离屏渲染。要保证所有的渲染操作在主窗口有视觉效果,需要激活默认帧缓冲,绑定到0
glBindFramebuffer(GL_FRAMEBUFFER, 0);
在完成所有的帧缓冲操作之后,不要忘记删除这个帧缓冲对象:
glDeleteFramebuffers(1, &fbo);
当然,检查完整性之前,需要给帧缓冲附加一个附件。附件是一个内存位置,能够作为帧缓冲的一个缓冲,可以将其想象为一个图像。创建一个附件的话,有
两个选项:纹理 或者 渲染缓冲对象
下面分别看下两个选项&