当前位置: 首页 > news >正文

聊城市建设局网站/无锡网站推广公司

聊城市建设局网站,无锡网站推广公司,太原网站推广怎么做,外贸中东哪些产品好卖模板测试(Stencil Test): 当片段着色器处理完一个片段之后,模板测试(Stencil Test)会开始执行,和深度测试一样,它也可能会丢弃片段。接下来,被保留的片段会进入深度测试,它可能会丢弃更多的片段。模板测试…

模板测试(Stencil Test):

当片段着色器处理完一个片段之后,模板测试(Stencil Test)会开始执行,和深度测试一样,它也可能会丢弃片段。接下来,被保留的片段会进入深度测试,它可能会丢弃更多的片段。模板测试是根据又一个缓冲来进行的,它叫做模板缓冲(Stencil Buffer),我们可以在渲染的时候更新它来实现一些很有意思的效果。

一个模板缓冲中,(通常)每个模板值(Stencil Value)是8位的。所以每个像素/片段一共能有256种不同的模板值。我们可以将这些模板值设置为我们想要的值,然后当某一个片段有某一个模板值的时候,我们就可以选择丢弃或是保留这个片段了。

模板缓冲的一个简单的例子如下:

模板缓冲首先会被清除为0,之后在模板缓冲中使用1填充了一个空心矩形。场景中的片段将会只在片段的模板值为1的时候会被渲染(其它的都被丢弃了)。 

每个窗口库都需要为你配置一个模板缓冲。GLFW自动做了这件事,所以我们不需要告诉GLFW来创建一个,但其它的窗口库可能不会默认给你创建一个模板库,所以记得要查看库的文档。

测试和混合发生在渲染流程中的最后一个阶段,在这个阶段里,GPU主要的工作是逐片元操作,将片元的颜色以某种形式合并,得到最终在屏幕上显示的像素颜色。

在webgl中的测试有裁剪测试、透明的测试、模板测试以及深度测试。这几个测试都是高度可配置的,测试流程如下图:

模板缓冲: 

通常用户在启用模板缓冲的时候,会将整个模板缓冲中的所有片段模板值设置为0,从而丢弃所有的片段,然后再设置特定区域的模板值以及比较函数。GPU会读取用户设置的模板值,然后将该值和模板缓冲中该位置的模板值,按比较函数进行比较,最终决定是保留还是舍弃该片段,形成遮罩效果。在模板测试中有两个很重要的方法是stencilFunc和stencilOp,stencilFunc用来控制stencil的测试方式,得出测试结果。stencilOp根据结果决定要如何处理缓冲中的数据。

glStencilFunc :

glStencilFunc(GLenum func, GLint ref, GLuint mask)一共包含三个参数:

  • func:设置模板测试函数(Stencil Test Function)。这个测试函数将会应用到已储存的模板值上和glStencilFunc函数的ref值上。可用的选项有:GL_NEVER、GL_LESS、GL_LEQUAL、GL_GREATER、GL_GEQUAL、GL_EQUAL、GL_NOTEQUAL和GL_ALWAYS。它们的语义和深度缓冲的函数类似。
  • ref:设置了模板测试的参考值(Reference Value)。模板缓冲的内容将会与这个值进行比较。
  • mask:设置一个掩码,它将会与参考值和储存的模板值在测试比较它们之前进行与(AND)运算。初始情况下所有位都为1。

测试的时候,ref会先和mask做与运算,再将模板缓冲中的值与mask做与运算,最后把这两个与运算的值,代入比较函数得出结果。

所有的比较函数如下:

举个例子:

glStencilFunc(gl.GEQUAL, 1, 0xFF)

 先将参考值1与0xff做与运算得到运算结果:1,将运算结果再与"模板缓冲和0xff进行与运算的值"进行比较。判断是否满足前者大于后者,如果是的话模板测试成功,否则失败。

mask值设为0xff的时候,就等于直接拿参考值和模板缓冲值做比较。

想要禁用模板也可以将mask设置为0x00

经历了glStencilFunc之后,我们就知道模板测试是不是通过。接下来就要对模板缓冲进行操作,这就需要 glStencilOp这个函数了。

glStencilOp:

glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)一共包含三个选项,我们能够设定每个选项应该采取的行为:

  • sfail:模板测试失败时采取的行为。
  • dpfail:模板测试通过,但深度测试失败时采取的行为。
  • dppass:模板测试和深度测试都通过时采取的行为。

每个选项都可以选用以下的其中一种行为:

行为描述
gl.KEEP保持当前储存的模板值
gl.ZERO将模板缓冲值设置为0
gl.REPLACE将模板缓冲区值设置为glStencilFunc函数设置的ref
gl.INCR如果模板缓冲值小于最大值则将模板值加1
gl.INCR_WRAP与GL_INCR一样,但如果模板缓冲值超过了最大值则归零
gl.DECR如果模板缓冲值大于最小值则将模板值减1
gl.DECR_WRAP与GL_DECR一样,但如果模板缓冲值小于0则将其设置为最大值
gl.INVERT按位翻转当前的模板缓冲值

默认情况下glStencilOp是设置为(gl.KEEP, gl.KEEP, gl.KEEP)的,所以不论测试的结果是什么,模板缓冲都会保留它的值。默认的行为不会更新模板缓冲,所以如果你想写入模板缓冲的话你需要至少对其中一个选项设置不同的值。

通常我们这样设置:glStencilOp(gl..KEEP, gl.KEEP,gl.REPLACE),测试失败时保持原有值(KEEP),测试通过的参考值替换模板缓冲值(REPLACE

在webgl中模板测试默认是处于禁用状态,使用时需要手动开启,我们采用gl.enable来开启:

gl.enable(gl.STENCIL_TEST);

注意,和颜色和深度缓冲一样,我们也需要在每帧绘制之前清除模板缓冲。

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

如果想自己在webgl上写模板测试,需要在获取gl上下文对象时传入stencil的请求:

const gl = canvas.getContext("webgl",{stencil:true});

深度测试(Depth Test):

深度测试可以帮助实现3D渲染的物体遮挡效果 ,

深度缓冲就像颜色缓冲(Color Buffer)(储存所有的片段颜色)一样,在每个片段中储存了信息,并且(通常)和颜色缓冲有着一样的宽度和高度。深度缓冲是由窗口系统自动创建的,它会以16、24或32位float的形式储存它的深度值。在大部分的系统中,深度缓冲的精度都是24位的。

 当深度测试被启用的时候,OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为新的深度值。如果深度测试失败了,片段将会被丢弃。

深度缓冲是在片段着色器运行之后(以及模板测试运行之后)在屏幕空间中运行的。屏幕空间坐标与通过OpenGL的glViewport所定义的视口密切相关,并且可以直接使用GLSL内建变量gl_FragCoord从片段着色器中直接访问。gl_FragCoord的x和y分量代表了片段的屏幕空间坐标(其中(0, 0)位于左下角)。gl_FragCoord中也包含了一个z分量,它包含了片段真正的深度值z值就是需要与深度缓冲内容所对比的那个值。

深度测试默认是禁用的,所以如果要启用深度测试的话,我们需要用GL_DEPTH_TEST选项来启用它:

glEnable(GL_DEPTH_TEST);

当它启用的时候,如果一个片段通过了深度测试的话,OpenGL会在深度缓冲中储存该片段的z值;如果没有通过深度缓冲,则会丢弃该片段。如果你启用了深度缓冲,你还应该在每个渲染迭代之前使用GL_DEPTH_BUFFER_BIT来清除深度缓冲,否则你会仍在使用上一次渲染迭代中的写入的深度值:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

如果在某些情况下你会需要对所有片段都执行深度测试并丢弃相应的片段,但希望更新深度缓冲。也就是你在使用一个只读的(Read-only)深度缓冲。OpenGL允许我们禁用深度缓冲的写入,只需要设置它的深度掩码(Depth Mask)设置为GL_FALSE就可以了:

glDepthMask(GL_FALSE);

注意这只在深度测试被启用的时候才有效果。

深度测试函数

OpenGL允许我们修改深度测试中使用的比较运算符。这允许我们来控制OpenGL什么时候该通过或丢弃一个片段,什么时候去更新深度缓冲。我们可以调用glDepthFunc函数来设置比较运算符(或者说深度函数(Depth Function)):

glDepthFunc(GL_LESS);

这个函数接受下面表格中的比较运算符:

函数描述
GL_ALWAYS永远通过深度测试
GL_NEVER永远不通过深度测试
GL_LESS在片段深度值小于缓冲的深度值时通过测试
GL_EQUAL在片段深度值等于缓冲区的深度值时通过测试
GL_LEQUAL在片段深度值小于等于缓冲区的深度值时通过测试
GL_GREATER在片段深度值大于缓冲区的深度值时通过测试
GL_NOTEQUAL在片段深度值不等于缓冲区的深度值时通过测试
GL_GEQUAL在片段深度值大于等于缓冲区的深度值时通过测试

默认情况下使用的深度函数是GL_LESS,它将会丢弃深度值大于等于当前深度缓冲值的所有片段。

 如果想自己在webgl上写深度测试,需要在获取gl上下文对象时传入depth的请求:

const gl = canvas.getContext("webgl",{stencil:true,depth:true});

Creator中使用深度、模板测试:

打开TS引擎源码文件cocos\gfx\webgl\webgl-swapchain.ts(低版本打开cocos\gfx\webgl\webgl-device.ts)

有个initStates函数,引擎在这里初始化depth、stencil state:


function initStates (gl: WebGLRenderingContext) {gl.activeTexture(gl.TEXTURE0);gl.pixelStorei(gl.PACK_ALIGNMENT, 1);gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);gl.bindFramebuffer(gl.FRAMEBUFFER, null);// rasterizer stategl.enable(gl.SCISSOR_TEST);gl.enable(gl.CULL_FACE);gl.cullFace(gl.BACK);gl.frontFace(gl.CCW);gl.disable(gl.POLYGON_OFFSET_FILL);gl.polygonOffset(0.0, 0.0);// depth stencil stategl.enable(gl.DEPTH_TEST);gl.depthMask(true);gl.depthFunc(gl.LESS);gl.depthRange(0.0, 1.0);gl.stencilFuncSeparate(gl.FRONT, gl.ALWAYS, 1, 0xffff);gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP);gl.stencilMaskSeparate(gl.FRONT, 0xffff);gl.stencilFuncSeparate(gl.BACK, gl.ALWAYS, 1, 0xffff);gl.stencilOpSeparate(gl.BACK, gl.KEEP, gl.KEEP, gl.KEEP);gl.stencilMaskSeparate(gl.BACK, 0xffff);gl.disable(gl.STENCIL_TEST);// blend stategl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE);gl.disable(gl.BLEND);gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);gl.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ZERO);gl.colorMask(true, true, true, true);gl.blendColor(0.0, 0.0, 0.0, 0.0);
}

以上初始化的配置,主要针对3D对象,因为2D对象大多数包含透明像素,因此2D管线不需要进行深度测试,比如:对于builtin-sprite.effect这类2d shader中对应深度测试部分,都被默认关闭了:

除了可以在effect文件中初始化深度模板测试 , creator编辑器还可以在material文件中修改:

所有深度、模板测试相关的配置都可以在Pipeline States下修改。

下面我们做个案例:

 如图,结合相机位置和右下角相机拍摄出的画面来看,由于长方体柱子的深度值比其他模型的深度值要小,(由于深度测试函数是GL_LESS,深度值小的通过测试)使得长方体背后的模型的片段被剔除了,因此长方体遮挡住了其他物体(包括地面)。接下来我们对长方体的深度测试做一些配置修改,再看看显示效果:

1.关闭长方体模型材质中的的深度测试:

关闭长方体的深度测试表现的效果: 

 长方体关闭了深度测试后,没有了深度值,在它和其他模型重叠的地方,会被有深度的模型片段填充。

http://www.jmfq.cn/news/5331403.html

相关文章:

  • html网站建设流程图/网络广告策划
  • 网站建设定制单/全国免费信息发布平台
  • 一个好的网站怎么建设/网站404页面怎么做
  • 石狮建设网站/网络营销网
  • 上海哪学网站建设优化/seo是什么味
  • 学院二级网站建设方案模板/sem搜索引擎
  • 厦门外贸网站建设 之家/杭州优化公司多少钱
  • 网站建设公司介绍ppt/软文广告投放平台
  • 温州网站网站建设/网站优化和网站推广
  • 陕西省建设造价协会网站/长沙网站关键词推广
  • 建设个人网站教程/百度竞价项目
  • 网站建设与设计教程/西安关键词优化服务
  • 沈阳建设银行网站/百度浏览器官方网站
  • 专业网站建设的意义/搜索词排行榜
  • 市城乡规划建设局网站/广州今日头条新闻
  • 徐州公司网站建设/一个具体网站的seo优化方案
  • 手机旅游网站建设/永久免费个人网站注册
  • 网站建设的工作在哪里找客户资源/重庆森林经典台词
  • 赤峰城乡建设委员会网站/如何做网站关键词优化
  • 湖南住房和城乡建设厅网站/百度排名服务
  • 所有北京网站建设公司/免费b站网站推广
  • 中国建设银行个人网上银行官方网站/外包网络推广
  • wordpress网站首页链接乱码/郑州seo服务公司
  • 宜宾网站建设88sou/河南网站seo靠谱
  • 分类网站建设与开发/友情链接的四个技巧
  • 越南网站建设/网站怎么进入
  • 横峰县城乡建设网站/运营推广公司
  • 西安航空城建设发展集团网站/企业seo网络推广
  • 合肥建设局网站首页/百度灰色关键词排名
  • 麻章网站建设公司/seo网络推广优化