原理

在光栅化时,GPUs会在同一时刻并行运行很多Fragment Shader,但是并不是一个Pixel一个Pixel去执行的,而是将其组织在2x2的一组Pixels分块中,去并行执行。而偏导数(dFdx、dFdy)就正好是计算的这一块像素中的变化率。

GLSL
// 以下v可以是任何类型
dFdx(v) = 该像素点右边的v值 - 该像素点的v值;
dFdy(v) = 该像素点下边的v值 - 该像素点的v值;
fwidth(v) = abs(dFdx(v)) + abs(dFdy(v));

fwidth即计算出当前像素在横坐标和纵坐标的总变化率。

坑

HLSL
if(condition)
{
	ddx(...)
}

如果 condition 在 pixel quad 内不同,就会 undefined behavior。

ddx/ddy 依赖 pixel quad,因此不能在非 uniform 分支中使用,否则结果未定义。

应用

判断 Mipmap

简单示例:

HLSL
float2 dx = ddx(uv);
float2 dy = ddy(uv);

float rho = max(length(dx), length(dy));

float mip = log2(rho * 1024);

if (mip > 6)
    return baseColor;
else
    return tex2D(detailTex, uv);

寻边

略

顶点偏移时重计算法线

{{< link title=“顶点偏移后的法线重计算” url="/posts/3d253bb1#ddx & ddy" icon="/favicon.ico" >}}

在片元阶段重建完整 TBN

{{< link title=“在片元阶段重建完整 TBN” url="/posts/7087033e" icon="/favicon.ico" >}}

: Cheyne Xie

: https://chaim.eu.org/posts/ad4c5022/

: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.