【WebGL】GPU计算法线和世界坐标系下精度问题的解决思路

1、法线计算

WebGL在片元着色器中提供了用于计算偏导数的函数 dFdx 和 dFdy,它们用于计算某种类型的值相对于屏幕空间坐标的变化率。
通俗来讲,对某个值求偏导,就是当屏幕坐标沿 x 轴前进 1 个像素或者沿 y 轴前进 1个像素时,该值的变化量。下面这张图可以很好地帮助理解(图片引用自An introduction to shader derivative functions

图1 偏导数的含义 

 

基于上述基本定义,几何体上三角面片的法线计算就有了思路。对空间坐标分别求 dFdx 和 dFdy。

假设屏幕坐标处的空间位置为 position(x, y),那么

dFdx(position(x, y)) = position(x + 1, y) - position(x, y)
dFdy(position(x, y)) = position(x, y + 1) - position(x, y)

这时 dFdx 和 dFdy 其实就是三角面片所在平面的两个向量,它们叉乘(cross)的结果就是当前屏幕坐标位置处的法向量

normal = cross(dFdx(position(x, y)), dFdy(position(x, y)));

2、世界坐标系下的精度问题

有时候我们需要在世界坐标系下计算片元的法线,而世界坐标往往是很大的数值,在GPU的单精度限制下会出现精度损失,从而导致计算出来的法线也存在精度问题。即相邻片元虽然在同一个三角面片上,但得出的法线方向会有所差异。为了说明这种精度损失的现象,我把这种情况下算出的法线的各个分量表达为颜色值,输出为一张图片,如图2所示。 

图2 GPU计算法线精度损失的情况 

 

可以看到很多“噪点”,根据这样的法线计算结果来做一些具体的应用,得到的结果往往也是会有很多“噪点”的。

我想到的一个解决思路是借助 WebGL 渲染管线在光栅化阶段对从顶点着色器传递到片元着色器的值做内插的特性:首先将片元着色器中通过偏导数计算得到的法线作为颜色值的各个分量离屏渲染到一张纹理上(render to texture),接着把这张纹理回过头来传给顶点着色器,顶点着色器中采样每个顶点位置的法线,最后内插到片元,这样就可以得到平滑的法线值了。图3是WebGL渲染管线的基本流程,这张图截取自《WebGL编程指南》一书。

图3 WebGL渲染管线在光栅化阶段的内插特性 

 

按这种方案得到的平滑法线输出为颜色类似图4的效果。这种方案虽然需要绘制两遍,但是能较好地规避世界坐标系下法线计算的精度问题。

 图4 GPU计算法线精度损失的解决方案

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值