graphics, rendering
Home

Artifacts with Phong Shading Normal

问题:物体边缘会有奇怪的黑边 #

最近用别人开源光追软件和自己光追软件的时候遇到了点bug,如下所示。

1

2

3

自己的渲染器也会遇上类似的问题。

image-20220521130708361

解答:法线插值的固有问题 #

后来上别人的仓库提了个issue,没想到是个typical question(又向歪果仁暴露了自己图形基础不扎实的事实)。原回答如下:

That is a usual artifact when rendering low-poly models with interpolated per-vertex shading normals.

At high geometry curvatures, which appear along the silhouettes of this object, it can happen that the interpolated shading normal across a triangle primitive actually doesn’t lie inside the same hemisphere as the direction to the viewer (negative ray direction) and that’s a false condition for the lighting test. For the shading calculation that’s like looking at the backface of an opaque object. (This would not happen when using the face-normals instead of the shading normals, but then you get a facetted look.)

Similar effects would arise when the sampled continuation ray in a path tracer would continue below the geometric surface of opaque materials, which also happens regularly with bump- or normal-maps.

This site has some nice images explaining interpolated shading normals: scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/shading-normals

The black areas are running into the dot(V, N) < 0.0 case.

it’s know topic with possible mitigation stragegies as per the publication “Consistent Normal Interpolation”, Reshetov et al., 2010 blog.yiningkarlli.com/2015/01/consistent-normal-interpolation.html and an implementation here

理解:直观感受 #

解释一下。

首先,我们做渲染时,一般会用插值的方法得到面片内某一点的法线。具体来说,我们shoot了一根ray,这根ray打到了一个三角形面片上的一个点。我们可以得到三角形三个顶点的法线和hit point的重心坐标,进而就可以插值出hit point的法线,一般管它叫shading normal。

这里会有一个问题,我们shoot出的ray打到了三角形面片,那我们其实是可以看到三角形面片上的所有点的,因为dot(viewDir, faceNormal)>0。但实际上在渲染时,我们会把某些点视为不可见,因为测试可见性的条件为dot(viewDir, shadingNormal)>0。如下图(灵魂画师):

image-20220521132007448

我们射出的ray(viewDir=-rayDir),打到了一个三角形面片上的点,和三角形的相交测试是使用face normal的,dot(faceNormal, viewDir)>0。但我们插值出来的shading normal,又会出现dot(shadingNormal, viewDir)<0的情况,进一步我们就不会在这个点上做光照计算,因此这块最后的颜色就黑了。

上面那篇siggraph asia的文章对这个问题提出了缓解办法。但我试过了,效果并不好。其实最简单的做法就是用face normal来做光照计算的测试,但这样最后渲染出来会有很强的面片效应。

image-20220521132406574

我已经放弃了对这个artifact进行进一步解决(摆烂ing)。