最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • WebGL-巧用模板缓冲实现区域高亮

    正文概述 掘金(多多洛爱学习)   2020-12-29   514

    区域高亮

    在重视可视化效果的地图应用场景中,常需要对指定区域高亮突出显示。传统的方法是覆盖一个高亮颜色的多边形,但在3D地图中平面多边形无法对区域内的3D模型进行覆盖,立体多边形又无法贴合3D模型的形状。另外,覆盖多边形也无法影响区域外部地区,当我们想要降低外部地区的亮度时就不能使用这种方案。

    如下图所示,我们希望达到右下的效果,区域内的模型均覆盖高亮色,而区域外的模型均覆盖阴影色。

    WebGL-巧用模板缓冲实现区域高亮

    解决方案

    几何碰撞

    比较直接的方案是采用几何碰撞计算,判断绘制物是否在高亮区域内以决定叠加哪种颜色,但几何计算CPU消耗高且无法解决跨区域内外的物体渲染问题。

    垂直投影映射

    若一个绘制物跨区域内外需要显示不同颜色,那可以在片元着色时进行处理,一种可行方案是在帧缓冲中渲染高亮区域平面多边形(在世界空间z=0平面,也就是地平面上)得到高亮纹理,在片元着色时通过垂直投影坐标读取高亮纹理色值,根据色值判断叠加哪种颜色。但此方案需要对每种绘制物的着色器都进行改动,维护成本较高。

    后处理方案

    若想在不改动各着色器的情况下叠加颜色,那就采用后处理吧。所谓后处理,是指在整个场景渲染完成之后对片元颜色进行后期修改,比如抗锯齿、泛光,以及之前介绍的雾化处理等。

    上述垂直投影映射方案可以改良到后处理阶段进行,需要前期在帧缓冲中进行场景渲染,这样后处理时我们可以通过帧缓冲得到颜色纹理和深度纹理,不过后处理阶段丢失了顶点坐标信息。这时对每个片元可以通过读取深度值结合纹理坐标推导NDC坐标,再通过视图投影逆矩阵反推世界坐标。世界坐标z置为0可以得到垂直投影坐标,将垂直投影坐标再变换到视窗中,再读取另一帧缓冲中的高亮纹理,即可决定片元叠加颜色。

    WebGL-巧用模板缓冲实现区域高亮

    听起来挺复杂,实际确实也需要在着色阶段在每个片元上执行相对复杂的计算。这复杂计算主要在于模板是平面区域的轮廓,所以我们需要将三维坐标点垂直投影到平面上才能与高亮纹理进行映射。那能不能得到立体区域的模板呢?

    立体区域判定

    其实可以通过深度测试来判定一个片元是否在立体区域中。如下图1所示,若一个片元被立体区域包裹(如A),那么它的深度必然介于立方体前后两个面之间,也就是只被一个面遮挡;若在立体区域之外(如B和C),那么它的深度是在立方体深度区域外的,要么被两个面遮挡,要么不被遮挡。反过来,如果我们在场景渲染完成后再绘制一个立方体,那么同一片元位置按理会再进行两次着色(关闭面剔除的情况下),若开启深度测试,但不进行深度写入,那么每个片元就会分为三种情况:不通过,通过1次,通过2次。那么只通过1次深度测试的片元就是在场景中处于立体区域内的片元,如下图2所示绿色标注部分。

    WebGL-巧用模板缓冲实现区域高亮

    模板缓冲

    但是如果直接进行着色,那么通过2次测试的片元颜色不好恢复,而且在立方体外的部分无法叠加阴影色,所以需要关闭颜色写入,先将通过1次测试的片元标记出来,再对整个视窗进行着色,这就需要使用模板测试了。

    模板测试同深度测试一样,是在光栅化之后对片元进行筛选,可以丢弃部分片元。模板测试也对应一个缓冲区,与颜色缓冲区大小相同,每一位存储模板值。模板测试可以用来实现一些有趣的效果,比如绘制物体轮廓等等。

    这里我们可以利用模板缓冲区可以对片元进行标记,通过WebGLRenderingContext.stencilOp(fail, zfail, zpass)可以设置模板缓冲区的写入操作,若通过深度测试则对模板值进行反转,其他情况则保持不变,即可标记出仅通过一次深度测试的片元。如下图所示:

    WebGL-巧用模板缓冲实现区域高亮

    整体方案

    结合以上分析,可以得到整体方案如下:

    1. 清空模板缓冲区:gl.clearStencil(0)
    2. 开启模板测试及深度测试,关闭颜色及深度写入
    3. 配置模板测试:gl.stencilFunc(gl.ALWAYS, 1, 0xff)即总是能够通过模板测试,gl.stencilOp(gl.KEEP, gl.KEEP, gl.INVERT)即通过深度测试则模板值反转,否则不变
    4. 写入模板:关闭面剔除,渲染高亮区域对应的立方体(高度可设置为1000米,即基本可以覆盖地图上的3D建筑模型)
    5. 关闭深度测试,开启颜色写入,关闭模板写入
    6. 叠加高亮色:设置gl.stencilFunc(gl.EQUAL, 0xff, 0xff),对颜色纹理进行图像处理,仅模板值为0xff的片元通过模板测试,进行高亮色的混合
    7. 叠加阴影色:设置gl.stencilFunc(gl.EQUAL, 0, 0xff),对颜色纹理进行图像处理,仅模板值为0的片元通过模板测试,进行阴影色的混合

    高亮效果如下: WebGL-巧用模板缓冲实现区域高亮


    更新 本方案没有考虑到相机进入立方体内部的情况,这种情况下立方体正面不会进行绘制,模板值不会进行二次反转,导致立方体内外颜色反转。暂时还没有想到很好的优化途径。


    起源地下载网 » WebGL-巧用模板缓冲实现区域高亮

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元