webgl centroid质心插值的一点理解

webgl,centroid,质心,插值,一点,理解 · 浏览次数 : 10

小编点评

质心插值是一种在对普通的varying变量进行插值时,采用几何边界所覆盖片元部分的一个质心点来参与插值计算的方法。它能确保最终光栅化的每个片元获取的数值都在顶点的值域范围内,避免超出值域范围的问题。 质心插值的具体计算方法取决于具体实现者的选择,但一般来说,如果覆盖了片元中心点,那么就用片元中心点进行插值;否则就使用几何边界与片元覆盖区域进行插值。 质心插值通常情况下影响不大,但如果代码中有一些内置函数依赖插值结果,并且可能出现异常情况,比如对一个插值求开平方,如果插值出来结果是负数,对负数求开平方就有问题。

正文

质心插值说的是什么

2023.10.04再次review这个细节点:
基本上把这个问题看明白了;centroid代表质心插值;问题来自于在对普通的varying变量进行插值时,默认都是采用片元中心点来进行计算获取最终插值,但是有些情况中心点并不在图形的覆盖范围内,这时候中心点插值就会超出当初设置的一个值域范围,导致在某些边界存在异常情况;比如上面链接中的代码,在蓝色区域竟然出现了黄色就有问题。
 
产生这个问题的原因在于,针对离散的片元在进行光栅化差值时候,有些片元虽然只有少部分被几何区域覆盖,但这些片元也参与光栅化并被作为图形的一部分;这就导致使用片元中心点参与插值计算时,得到的计算结果会不在顶点的值域范围内。
而质心插值采用的是,几何边界所覆盖片元部分的一个质心点来参与插值计算。这样就能够保证最终光栅化的每个片元获取的数值都在顶点的值域范围内。
下面这个示例就是在表达这种情况:
左边没有使用质心插值,在下面代码构造的场景中就会出现超出值域范围(0-1)的问题;右边采用了质心插值,则没有出现这个问题。
<!-- WebGL 2 shaders -->
    <script id="vs-render" type="x-shader/x-vertex">
        #version 300 es
        #define POSITION_LOCATION 0
        #define ATTRIBUTE_DATA_LOCATION 6
        
        precision highp float;
        precision highp int;

        uniform mat4 MVP;

        layout(location = POSITION_LOCATION) in vec2 position;
        layout(location = ATTRIBUTE_DATA_LOCATION) in float data;
        
        out float v_attribute;

        void main()
        {
            gl_Position = MVP * vec4(position, 0.0, 1.0);
            v_attribute = data;
        }
    </script>

    <script id="fs-render" type="x-shader/x-fragment">
        #version 300 es
        precision highp float;
        precision highp int;

        in float v_attribute;
        out vec4 color;

        void main()
        {
            const vec4 blue   = vec4( 0.0, 0.0, 1.0, 1.0 );
            const vec4 yellow = vec4( 1.0, 1.0, 0.0, 1.0 );
            color = v_attribute >= 0.0 ? mix(blue, yellow, sqrt(v_attribute)) : yellow;
        }
    </script>
    
    <script id="vs-render-centroid" type="x-shader/x-vertex">
        #version 300 es
        #define POSITION_LOCATION 0
        #define ATTRIBUTE_DATA_LOCATION 6
        
        precision highp float;
        precision highp int;

        uniform mat4 MVP;

        layout(location = POSITION_LOCATION) in vec2 position;
        layout(location = ATTRIBUTE_DATA_LOCATION) in float data;
        
        centroid out float v_attribute;

        void main()
        {
            gl_Position = MVP * vec4(position, 0.0, 1.0);
            v_attribute = data;
        }
    </script>
    
    <script id="fs-render-centroid" type="x-shader/x-fragment">
        #version 300 es
        precision highp float;
        precision highp int;

        centroid in float v_attribute;
        out vec4 color;

        void main()
        {
            const vec4 blue   = vec4( 0.0, 0.0, 1.0, 1.0 );
            const vec4 yellow = vec4( 1.0, 1.0, 0.0, 1.0 );
            color = v_attribute >= 0.0 ? mix(blue, yellow, sqrt(v_attribute)) : yellow;
        }
    </script>
那么质心怎么计算?
OpenGL allows implementers to choose the ideal centroid, or any location that is inside the intersection of the pixel square and the primitive, such as a sample point or a pixel center.
意思就是OpenGL规范允许具体实现者自己来决定,可以使用几何覆盖区域的中心点,或者直接使用片元的中心点也可以(当然这时候会有问题)。目前看起来当声明了使用质心插值时,大多数显卡的实现方式是,如果覆盖了片元中心点那么就是用片元中心点就是用中心点计算插值,当没有覆盖中心点就是用几何边界与片元覆盖区域(是一个三角形)计算出三角形质心(有专门的计算公式。
 

到底该不该用

质心插值也不是什么时候都适用,大部分时候影响不大(如果重要webgl1不会舍弃)。如果你的代码里有一些内置函数依赖插值结果,并且可能出现异常情况,比如对一个插值求开平方,如果插值出来结果是负数,对负数求开平方就有问题。

其次当着色器中代码逻辑,因为这个超出值域范围的数字影响特别大时候需要处理,比如对一个数求高次的幂逻辑。
 
也有一些情况不适用质心插值。比如代码中使用了一些导数计算,如dfx、dfy,因为他们的步长和方向都已经变了(delta的取值不再是两个片元的中心点差值了);另外如果非质心插值对效果影响不大可以不用管他,因为它的开销还是比较大。

 

 

 

与webgl centroid质心插值的一点理解相似的内容:

webgl centroid质心插值的一点理解

质心插值说的是什么 2023.10.04再次review这个细节点: https://www.opengl.org/pipeline/article/vol003_6/ https://github.com/WebGLSamples/WebGL2Samples/blob/master/samples

WebGL:使用着色器进行几何造型

本文将介绍如何使用着色器来进行几何造型,说到几何图形大家一定都不陌生,比如说三角形、圆形,在WebGL中除了直接使用顶点绘制,我们还可以使用片元着色器进行造型,以下将介绍三角形的绘制,以及应用场景。

WebGL实现简易的局部“马赛克”

在Canvas2D中通过调用`drawImage` API就能将图像绘制到画布上,在WebGL中我们也可以绘制图像,在绘制时我们需要用到WebGL中的纹理对象,在之前实现网格背景的视频中,我使用了一个叫做纹理坐标的配置,现在要完成纹理的加载我们也需要用到纹理坐标,并且我们可以通过对纹理坐标处理实现简...

可视化学习:如何用WebGL绘制3D物体

在学习2D绘图的时候,我们提过很多次关于GPU的高效渲染,但是2D图形的绘制只展示了WebGL部分的能力,WebGL更强大的地方在于,它可以绘制各种3D图形,而3D图形能够极大地增强可视化的表现能力。相信很多小伙伴都对此有所耳闻,也有不少人学习WebGL,就是冲着它的3D绘图能力。接下来,文本就用一...

如何基于three.js(webgl)引擎架构,研发一套通过配置就能自动生成的3D机房系统

自动化3D机房、微模块、3D机房、3D数据中心、科技感数据中心、三维机房、3d建筑,3d消防,消防演习模拟,3d库房,3d档案室,3d密集架,webGL,threejs,3d机房,bim管理系统

如何使用webgl(three.js)实现煤矿隧道、井下人员定位、掘进面、纵采面可视化解决方案——第十九课(一)

three.js、webgl、3D煤矿隧道、三维井下人员定位、掘进面三维可视化、纵采面可视化、采集面可视化展示、设备检测、数字孪生、物联网3D、3d建筑、3d库房,bim管理系统

three.js高性能渲染室外场景

大家好,本文在相关文章的基础上,使用three.js渲染了高性能的室外场景,在移动端也有较好的性能,并给出了代码,分析了关键点,感谢大家~ 关键词:three.js、Web3D、WebGL、室外场景、Instanced Draw、大场景、LOD、Frustum Cull、优化、开源 代码:Githu

three.js实现相机碰撞,相机不穿墙壁、物体

大家好,本文实现了相机碰撞检测,使相机不穿墙壁、物体,并给出了思路和代码,感谢大家~ 关键词:数字孪生、three.js、Web3D、WebGL、相机碰撞、游戏相机 我正在承接Web3D数字孪生项目,具体介绍可看承接各种Web3D业务 目录实现原理参考资料 实现前: 移动第三人称相机时,相机可能会穿

第135篇:Three.js基础入门

好家伙,这东西太帅了,我要学会 先放张帅图(都是用three.js做出来的,这我学习动力直接拉满) 还有另外一个 Junni is... 帧数太高,录不了 开始学习 官方文档 1.Three.js是什么? Three.js是一款运行在浏览器中的 3D 引擎(基于WebGL的API的封装),你可以用它