逐片元操作前的操作
目前我们获取的数据包含顶点数据和纹理数据两部分,而由前面的信息已知,在一个多文件的复杂模型中,除了顶点坐标和纹理坐标之外的数据都可以通过纹理文件的方式在片元着色器中完成。
顶点坐标数据传入后,在几何阶段通过顶点着色器的MVP变换得到新顶点坐标,再通过内置视口变换传到下一阶段。(对于视口的兼容已经通过在P变换中考虑视口大小完成)
下一阶段为光栅化阶段,顶点坐标数据用于设置三角形(面元),三角形被拆分成片元(一个片元对应缓冲区一个点,一个像素),进入片元着色器计算颜色,传入逐片元操作中。
传入逐片元操作的三大缓冲区:颜色缓冲区、模板缓冲区、深度缓冲区。(模板stencil)
深度测试所需要数据的来源
在顶点着色器中我们将变换后的顶点数据提供给了gl_Position
变量。
在片元着色器中,同样也有自动计算出的gl_FragCoords
变量可以用于我们查看当前片元的坐标,其中xy通常不作处理,但是z坐标是可以用于后续的深度缓冲的,同时也可以用于给FragColor
赋值用于向颜色缓冲区输出深度数据,得到深度图。
这里的z坐标和原始深度是完全不同的,因为projection变换的深度变形,
结果就是距离近的z其精度比线性高,而远处z精度低于线性。在生成深度图时要考虑到这一点。这样的结果也利于防止z-fighting。
逐片元操作
逐片元操作作为通常意义上光栅化阶段的最后一步,同时也是着色的最后一步,其数据来源是三个系统管理的缓冲区,和一些关联数据,逐片元操作也会修改这些缓冲区。
通常认为包含Pixel Ownership Test、Scissor Test、Alpha Test、Stencil Test、Depth Test、Blending、Dithering、Logic Op,最终完成了颜色缓冲区并输出,而其他缓冲区则只是用来计算颜色缓冲区。
和先期操作不同,逐片元操作是不可编程的,但是可以手动设置其属性,不同步骤的灵活度不同。
Pixel Ownership Test是确定像素是否在窗口内,这一步通常不是手动的,它检查全桌面像素。
Scissor Test从窗口内选择用于下步操作的区域,这一步通常手动,它检查全窗口像素。通常这一步操作是为了将2dUI和3d显示器结合起来而设计的。
Alpha Test仅用于剔除alpha值不符合条件的片元,Blending步骤才用于处理透明片元。
Stencil Test同样是选择一部分像素通过,但是它的作用通常是在由一个shader program控制的区域中挖出一个区域提供给另一个shader program使用,相当灵活。
Depth Test的作用和灵活度相比Stencil Test差远,它的作用基本上仅为控制片元重叠时的显示策略,并且通常使最前的片元显示。但是它的通过与否能控制Stencil Buffer。
简述Stencil和Depth Test
有一系列函数:
-
glStencilOp(GLenum sfail, GLenum dpfail, GLenumd ppass)
-
glStencilFunc(GLenum func, GLint ref, GLuint mask)
-
glStencilMask(GLuint mask)
-
glDepthFunc(GLenum func)
-
glDepthMask()
对于func类函数,GLenum func
通常指如GL_LESS
、GL_NOTEQUAL
、GL_ALWAYS
等测试策略。
对于mask类函数,模板测试的GLuint mask
会在操作将要修改缓冲区前,将数据做按位与运算后再修改。深度测试的参数则为GL_TRUE
和GL_FALSE
,它控制了当深度测试成功时是否将深度数据修改进深度缓冲区。
而对于特殊的glStencilOp
,事实上同时结合了深度测试结果和模板测试结果,用于修改模板缓冲区。
func控制通过与否,mask控制是否允许修改,分别是最后一步。
深度缓冲区是自动管理的,当glDepthMask(GL_FALSE)
时,不允许用成功深度值替换原值;否则每次成功后深度缓冲区都会自动更新。
模板缓冲区通过glStencilOp
半自动管理,要使修改不能进行,使用glStencilMask(0x00)
,或者保持glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP)
。(与此同时Scissor Test范围可以认为几乎是默认值或手动控制)
要避免多次改变glStencilOp
,通常通过glStencilMask
。
深入
模板缓冲区是8位整型数据,而深度缓冲区通常是32位浮点型数据。
而模板缓冲的8位整型为模板分类提供了便利,因为可以使用不同mask筛选出模板缓冲中具有对应数值的片元,使它们通过测试修改缓冲区。
glStencilOp
的三个参数分别为未通过模板测试的修改法、未通过深度测试的修改法、都通过的修改法,而glClear
会将缓冲区全部置0。
为了修改深度缓冲,通常使用GL_REPLACE
代替GL_KEEP
,这会让通过测试的片元使用glStencilFunc
中的ref参数填充深度缓冲。
而使用模板的时候,如果希望不修改缓冲区,且要求模板还能再构造,需要glStencilMask
。
由此延伸出的视觉效果包含任何需要在某区域运行不同渲染程序、渲染不同对象的情况,如反射、折射、传送门、侦探游戏等。
其实还有其他用法,因为它也可以用于为要渲染的模型挖洞,只要目标模型的片元处模板缓冲区与别处不同,如物体边缘、选中状态。
(Blending一时间学不了了)
comment 评论区
star_outline 咱快来抢个沙发吧!