一个愚蠢的漫反射着色模型
A silly diffuse shading model

原始链接: https://lisyarus.github.io/blog/posts/a-silly-diffuse-shading-model.html

这篇帖子探讨了一种令人惊讶地有效、简化的漫反射着色模型,用于快速渲染测试。标准的漫反射模型 `max(0, L⋅N)` 在几何上是正确的,但会在背对光源的表面上产生生硬的、未着色的区域——在没有环境光或纹理的情况下,看起来完全是黑色。 为了解决这个问题,作者提出了一种“愚蠢”但实用的替代方案:`(0.5 + 0.5 * (L⋅N))^2`。这个公式重新映射点积,避免了黑色斑点,即使在未直接被照亮的表面上也能提供着色。虽然不完全符合物理规律,但它近似于定向光与环境贴图甚至次表面散射的外观。 有趣的是,这个解决方案并非随意为之。它是数学上最优的——赫米特插值的结果,确保简化公式在关键点上与原始公式的值和导数匹配。作者在云渲染工作期间开发了这个单行着色模型,并发现它对于优先考虑速度和简洁性的项目来说,是一个实用且视觉上令人愉悦的解决方案,而无需严格的物理准确性。

黑客新闻 新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 一个简单的漫反射着色模型 (lisyarus.github.io) 5 分,ibobev 发表于 1 小时前 | 隐藏 | 过去 | 收藏 | 1 条评论 dewitt 发表于 17 分钟前 [–] “一个更傻的解决方案”下的艺术风格 [1] 让我想起了 1985 年 8 月《龙》杂志第 100 期封面 [2]。 [1] https://lisyarus.github.io/blog/media/a-silly-diffuse-shadin... [2] https://archive.org/details/DragonMagazine260_201801/DragonM... 回复 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文

A silly diffuse shading model


Happy New Year for those who celebrate!

Happy Arbitrarily Chosen Point in Earth's Orbit for those how don't!

We all know that the proper lighting factor (i.e. proportion of reflected incoming light) for a completely diffuse (aka Lambertian) surface is \(\max(0, L\cdot N)\). Here, \(L\) is the direction to the light source, \(N\) is the surface normal, and \(\cdot\) is the dot product. The dot product essentially comes from pure geometry (the same amount of light in a light beam cross-section being spread across larger surface area), while the \(\max\) is there to make sure that the parts of the surface facing away from light don't receive any light at all.

Is it a great, physically reasonable model (although real materials don't exactly look like that), and serves as a basis for many other shading models (typically via microfacet theory for modern PBR materials). However, sometimes we don't care about such things; sometimes we've just started a new project or a rendering tech demo and we just want to throw some good one-liner shading model. We don't have a texture or even don't intend to, we just want something reasonable to look at.

And here the diffuse model sucks! The \(\max(0, \dots)\) part makes half of the model (the one not facing the light) completely flat-colored (e.g. just black if you don't have ambient light), making you unable to see any geometry.


Notice the black parts!

Btw, all screenshots in this post have light intensity of 1, have gamma-correction, and no other post-processing (i.e. no tone-mapping).

Can we do better?

Contents

Typical solutions

Now, of course it's not a new problem. In typical scenes this effect isn't seen because we have many different lights (so the black part is much smaller), we have textures (so with some ambient light there is still variation in the color), we have some form of ambient occlusion (which further provides visual clues about the geometry), etc, etc.

All these solutions are, however, not one-liners like the max(0, dot(L, N)) thing, and range in complexity from rather simple (e.g. hard-coding two or three lights in the shader) to academic-level state-of-the-art (like GTAO and similar algorithms). For something like a test project we would definitely prefer a one-liner!

A silly solution

One simple way to fix this is to just re-map the dot product values from \([-1, 1]\) to \([0, 1]\) with a linear function. This results in a formula

\[ 0.5 + 0.5 \cdot (L\cdot N) = \frac{1 + L\cdot N}{2} \]

Here's what it looks like:

It's much better, and there are no completely black spots, but the image is much brighter than it should be. It makes sense — after all, we changed the formula! Comparing the plots of intensity as a function of the dot product makes it especially apparent:


Red is correct formula, blue is tweaked formula

It's not exactly physical, but it probably can be put on rigorous grounds if we replace a single directional light source with a suitable environment map, e.g. one that has light in one hemisphere and doesn't have it in the other hemisphere (though I didn't check the math). That's what I've been doing for ages, but maybe we can do even better?

A sillier solution

Behold:

\[ \left(0.5 + 0.5 \cdot (L\cdot N)\right)^2 = \left(\frac{1 + L\cdot N}{2}\right)^2 \]

Yep, I just squared the formula from the previous section! Here's what it looks like:

It's much closer to the true image in well-lit areas, yet still has nice shading gradients where the surface isn't facing the light. It's not exactly physical either, though we might hand-wavingly say that it approximates subsurface scattering of some sort. And here's the plot:


Red is correct formula, orange is new formula

It's clearly some sort of an approximation of the true formula! How come?

Hermite problems

If you look closely at the last plot above, you'll notice that

  • Both functions have the same values at \(-1\) and \(1\)
  • Both functions have the same slope (i.e. derivative) at \(-1\) and \(1\)

What if we turn things upside down and instead ask for a function that matches the values and derivatives of \(f(x) = \max(0, x)\) at \(x=\pm 1\)?

Guess what, mathematicians know exactly how to do this! This is called Hermite interpolation, and is solvable with an exact formula! If you specify \(N+1\) values and derivatives at various points, Hermite interpolation gives you the unique polynomial of order \(\leq N\) which has these values and derivatives.

In our case we have \(N=3\) (we have two values + two derivatives, thus \(N+1=4\)), so we expect at most a cubic polynomial. In this special case it turns out that the solution is not cubic, but quadratic, and is exactly \(\left(\frac{1+x}{2}\right)^2\). So this shading model is even optimal in some sense!

Hermite interpolation is also fun from algebraic perspective — it's actually an instance of the Chinese remainder theorem (for polynomial rings), which in modern form is neither Chinese nor about remainders.

That's it

I actually developed (well, more like randomly made up) this shading model while working on clouds in my game — they use exactly this formula, and I'm more than happy with how it looks:

That's it, and thanks for reading!

End section

联系我们 contact @ memedata.com