fwidth
函数是一个GLSL内置函数,用于计算函数在屏幕空间(或者其他坐标系)中x和y方向的变化率,也就是函数沿着x和y方向的梯度。
fwidth(in vec2 p) -> vec2
p
:要计算梯度的坐标。返回一个二维向量,向量的x分量表示函数沿着x轴的梯度,y分量表示函数沿着y轴的梯度。
fwidth
函数将在输入坐标周围做一个小的增量来计算梯度。这个增量通常等于纹理坐标的分辨率。
对于输入坐标p
,fwidth(p)
的计算公式如下:
fwidth(p) = abs(dFdx(p)) + abs(dFdy(p))
其中:
abs
函数表示取绝对值。dFdx(p)
表示函数在x轴上的偏导数。dFdy(p)
表示函数在y轴上的偏导数。在默认情况下,fwidth
函数是在片段着色器中使用的,通常用于计算像素变化、纹理采样和着色器后期处理等方面。
下面是一个示例片元着色器,使用fwidth
函数计算表面法线的偏导数,结果用于计算环境光的强度:
uniform vec3 ambientColor;
uniform vec3 lightColor;
uniform vec3 lightDir;
varying vec3 vNormal;
void main() {
vec3 n = normalize(vNormal);
vec3 l = normalize(lightDir);
float NdotL = dot(n, l);
float intensity = max(0.0, NdotL);
// 计算法线的偏导数
vec2 derivative = fwidth(gl_FragCoord.xy);
// 加权环境光颜色
vec3 ambient = ambientColor * (1.0 - intensity*intensity);
vec3 color = ambient + intensity * lightColor;
// 应用边缘柔化
color *= exp(-(derivative.x + derivative.y));
gl_FragColor = vec4(color, 1.0);
}
您可以使用实际环境光颜色和光线方向替换shader中的uniform变量,以获得更好的结果。