demo演示
模板stencil测试
- OpenGL颜色缓冲区是用于存储渲染图像的颜色数据的内存区域,在每个新的渲染迭代,我们都将屏幕颜色清理glClearColor()为我们指定的颜色,然后同时清除glClear()颜色缓冲区,
- 颜色缓冲——模板测试——深度测试——决定是否绘制片段
- 当片段着色器处理完一个片段之后,模板测试开始执行,我们可以决定丢弃还是保留某个片段,被保留的片段会进入深度测试,再次决定是否保留。
- 每个像素模板值是8位的,转为2进制01的形式,有256种(16*16的位置)不同的模板值。一般情况下,一个像素的所有位置都设置为统一的值(0/1)
- 相比深度测试来说,stencil测试可以有更加灵活的控制能力
- 我们可以启用glEnable()(就会执行模板测试),和掩码glStencilMask(0x00);,并设置glStencilOp(),glStencilFunc(),设置当前的状态
- glStencilMask位掩码:当发生写入时,会与这个写入的模板值进行与(AND)运算,0xFF所有位都为1,会保留写入的模板值,0x00模板值的所有位都会变成0.
- 模板函数:
- glStencilOp()(不同情况下对模板缓冲采取的行为,更新模板值):状态:
- 模板测试失败时,
- 模板测试通过但深度测试失败时,
- 模板测试和深度测试都通过时
- glStencilFunc()函数(决定是否通过测试,没有通过测试的片段会被丢弃):
- 测试函数(和深度测试中一样,这回是当前模板值和参考值比较),
- 参考值(模板缓冲中的内容将会与这个值进行比较),
- 掩码(在测试比较它们之前进行与(AND)运算)
- glStencilOp()(不同情况下对模板缓冲采取的行为,更新模板值):状态:
- 绘制物体轮廓:
- 在while循环中,glStencilOp()设置行为函数,在模板和深度都通过测试,GL_REPLACEglStencilFunc函数设置的
ref
值,深度测试不通过,我们也没必要进行绘制,更新它的模板值 - 在while循环中,glStencilFunc(GL_ALWAYS, 0, 0xFF);让绘制的物体都通过绘制,正常绘制,因为通过了测试,模板值设置为0,
- 到了我们想要绘制轮廓的物体,把物体模板值设置为1,glStencilFunc(GL_ALWAYS, 1, 0xFF);
- 用新的着色器渲染放大物体,这回的glStencilFunc(GL_NOTEQUAL, 1, 0xFF);测试函数,只有当模板值不为1才会渲染,物体模板值设置为不会被更新
- 在while循环中,glStencilOp()设置行为函数,在模板和深度都通过测试,GL_REPLACEglStencilFunc函数设置的
Blend混合
- 丢弃片段:GLSL中discard命令,让片段不会进入颜色缓冲,可以判断texture()的颜色值vec4.a的透明度,如果<0.1调用discard命令
- 混合:
- 渲染一个片段,要么完全丢弃它,要想渲染有多个透明度级别的图像,glEnable启用混合,
- 时间段:片段着色器运行完成后,所有的测试都通过之后,执行混合方程,应用到当前片段(颜色)和颜色缓冲上(之前片段的颜色,存储到缓冲)
- 混合方程:源颜色*目标颜色(最终颜色),+ ,源因子*目标因子(我们可以决定源因子和目标因子的值)
- 转换一下计算影响:源颜色*源因子 + 目标颜色*目标因子
- 这个混合方程的因子怎么设定?glBlendFunc(源因子的选项,目标因子的选项),
- 问题:后绘制的透明窗户,如果在后面,会被丢弃片段,
- 原因:深度缓冲不会检查片段是否是透明的,深度测试未通过,深度测试仍然丢弃了它们
- 解决:从后往前绘制,后面的会绘制完成,前面的片段不会丢弃掉,并会运用混合方程,并且不透明物体也要先绘制,同样防止片段被丢弃。
- 具体思路:建立map数据结构<与相机距离,位置值>,建立迭代器,从小到大的距离,获取到位置值,传入glsl的model中,设置位置并绘制