glPolygonOffset中的公式的一些思考

glPolygonOffset可以用于对光栅化后的fragment深度进行偏移,在后续depth test时将使用偏移后的深度。这个函数很常见的一个应用是在shadow mapping中缓解shadow acne。

OpenGL 4.5 spec, 14.6.5中提到了glPolygonOffset使用的公式,如下

o = m ∗ f a c t o r + r ∗ u n i t s o = m * factor + r * units o=mfactor+runits

其中m可以使用两种定义,分别为

( 1 ) m = ∂ z w ∂ x w 2 + ∂ z w ∂ y w 2 ( 2 ) m = m a x { ∣ ∂ z w ∂ x w ∣ , ∣ ∂ z w ∂ y w ∣ } \begin{aligned} (1)\quad m &= \sqrt{\frac{\partial z_w}{\partial x_w}^2+\frac{\partial z_w}{\partial y_w}^2}\\ (2)\quad m &= \mathrm{max}\left \{\left |\frac{\partial z_w}{\partial x_w} \right |,\left |\frac{\partial z_w}{\partial y_w}\right | \right \} \end{aligned} (1)m(2)m=xwzw2+ywzw2 =max{xwzw,ywzw}

其中(1)是梯度的大小,而(2)是两个偏导数中绝对值较大的一个(与glsl中fwidth函数的结果一样)。这里 x , y x,y x,y方向的导数在整个三角形内都是常数

下面来探讨下为什么会使用上面两种表示可能的原因。

如果将一个像素想象成一个square,由于sampling都是在像素中心进行,要找到在像素范围内最大的偏移,我们可以使用下面的函数(为了简化讨论,我们在单位定义域内进行),并求取最大值

f ( x , y ) = ∣ ∂ z w ∂ x w ( x − 0.5 ) + ∂ z w ∂ y w ( y − 0.5 ) ∣ , x , y ∈ [ 0 , 1 ] × [ 0 , 1 ] f(x,y)=\left |\frac{\partial z_w}{\partial x_w}(x-0.5)+\frac{\partial z_w}{\partial y_w}(y-0.5)\right |,x,y \in [0,1]\times[0,1] f(x,y)=xwzw(x0.5)+ywzw(y0.5)x,y[0,1]×[0,1]

该函数可以通过方向导数得到。经过简单计算,我们可以得到最大值为

f m a x = 1 2 ( ∣ ∂ z w ∂ x w ∣ + ∣ ∂ z w ∂ y w ∣ ) f_{max}=\frac{1}{2}\left(\left |\frac{\partial z_w}{\partial x_w}\right|+\left |\frac{\partial z_w}{\partial y_w}\right|\right) fmax=21(xwzw+ywzw)

这里有意思的一点是,该最大值还满足如下不等式(来自SO上网友的评论

1 2 ( ∣ ∂ z w ∂ x w ∣ + ∣ ∂ z w ∂ y w ∣ ) ≤ m a x { ∣ ∂ z w ∂ x w ∣ , ∣ ∂ z w ∂ y w ∣ } ≤ ∂ z w ∂ x w 2 + ∂ z w ∂ y w 2 \frac{1}{2}\left(\left |\frac{\partial z_w}{\partial x_w}\right|+\left |\frac{\partial z_w}{\partial y_w}\right|\right) \le \mathrm{max} \left \{\left |\frac{\partial z_w}{\partial x_w}\right|,\left |\frac{\partial z_w}{\partial y_w}\right| \right \} \le \sqrt{\frac{\partial z_w}{\partial x_w}^2+\frac{\partial z_w}{\partial y_w}^2} 21(xwzw+ywzw)max{xwzw,ywzw}xwzw2+ywzw2

由于gpu可以做近似计算,所以只要比 f m a x f_{max} fmax大就可以满足要求,所以使用(1)(2)都是满足需求的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenGL,绘制光影的三角形通常使用阴影映射技术。阴影映射是一种将场景的深度信息映射到纹理,并将该纹理用于渲染阴影的技术。 以下是使用OpenGL绘制光影三角形的一般步骤: 1. 渲染深度贴图:首先需要渲染场景的深度信息到一个纹理。这可以通过使用帧缓冲对象和深度缓冲区完成。首先,我们需要创建一个帧缓冲对象和一个纹理附件,将深度缓冲区附加到帧缓冲对象上。然后,将相机位置设置为光源位置,渲染场景,并将深度值写入深度缓冲区和纹理附件。 2. 渲染阴影:现在我们有了深度纹理,可以使用它来检测场景的阴影。在渲染场景时,我们需要将相机位置设置为观察者的位置,将投影矩阵设置为光源的视图投影矩阵,将深度纹理绑定为纹理单元,然后使用着色器将深度纹理的深度值与当前片段的深度值进行比较,从而确定当前片段是否在阴影。如果是,则将片段的颜色设置为黑色。 3. 绘制光影三角形:最后,我们需要绘制光影三角形,即将阴影转换为图形。可以使用glPolygonOffset函数来绘制深度值相同但在不同表面上的三角形,从而避免Z-fighting问题。该函数将对深度值进行偏移,使其与深度缓冲区的深度值不完全相同。 以上是绘制光影三角形的一般步骤。具体实现需要根据具体情况进行调整和修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值