Unity光线步进计算着色器SDF有向距离场法向量计算失效问题
问题原因
你编写的法向量计算函数存在笔误,每个分量的差分计算中减数与被减数完全相同,导致所有分量的计算结果均为0,最终输出全黑颜色。
原normal函数的三个分量计算逻辑均为sdf_box(偏移点) - sdf_box(同一个偏移点),两个相等的值相减结果为0,三个分量全0经过normalize处理后仍然是零向量,映射为RGB颜色就是纯黑。
修正后的代码
使用中心差分法的正确实现如下:
float EPSILON = 0.001f; float3 normal(float3 p) { float2 e = float2(EPSILON, 0); return normalize(float3( sdf_box(p + e.xyy) - sdf_box(p - e.xyy), sdf_box(p + e.yxy) - sdf_box(p - e.yxy), sdf_box(p + e.yyx) - sdf_box(p - e.yyx)) ); }
如果需要降低计算量,也可以使用前向差分实现:
float3 normal(float3 p) { const float EPSILON = 0.001f; float d = sdf_box(p); return normalize(float3( sdf_box(p + float3(EPSILON, 0, 0)) - d, sdf_box(p + float3(0, EPSILON, 0)) - d, sdf_box(p + float3(0, 0, EPSILON)) - d )); }
额外优化建议
你当前的立方体SDF实现可以简化,无需拆分x/y/z分别计算:
float sdf_box (float3 p) { const float3 center = float3(0.0f, 0.0f, 0.0f); const float3 size = float3(1.0f, 1.0f, 1.0f); float3 q = abs(p - center) - size * 0.5f; return length(max(q, 0.0f)) + min(max(q.x, max(q.y, q.z)), 0.0f); }
内容的提问来源于stack exchange,提问作者Jimmy Diddler
相关产品推荐
相关产品推荐

