MME 编写入门(五)简单光照模型 补充说明

本文由 简悦 SimpRead 转码, 原文地址 www.bilibili.com

作者:小林呓

在第四篇的简单光照模型中,做了一个简单的卡通着色器。

在第四篇的简单光照模型中,做了一个简单的卡通着色器。对的,讲的思路是冯氏着色的方法,但是最后做出来的实际上是卡通着色。

原因很简单,是因为像素着色器里 这一行的效果。

Color.rgb *= lerp(MaterialToon, float3(1,1,1), saturate(LightNormal * 16 + 0.5)

什么是 lerp?什么是 saturate?为什么要 LightNormal*16+0.5?

为了方便观察,在这里放置一个球。球可以在 PE 里快速建出,记得随便贴上个纯色的贴图,还有 toon。放上简单光照的 fx 效果,如图。光照部分和阴影部分有较为明显的二分。所以是非真实感渲染 (Non-Photorealistic Rendering) ,NPR。

实际上把后面的 * 16+0.5 删掉就可以得到 真实感渲染 (Photorealistic rendering)。

Color.rgb *= lerp(MaterialToon,float3(1,1,1),saturate(LightNormal))

为了看得更明显,所以这里调整了一下强度和颜色。可以看到这种层层的渐变效果。真实渲染 旨在渲染真实感的画面,而 NPR 则追求更加有艺术感的画面效果。

回到最开始的问题,什么是 lerp?

lerp 函数,是经常用的插值函数。其意义是 lerp(a,b,w),计算 a + w*(b-a),在 a 和 b 之间插值,w 表示权值,范围 0~1。

为了看得更明显,我们可以把前边的 MaterialToon 改成 float3(0,0,0),这样就是黑色,与白色,进行插值。

Color.rgb *= lerp(float3(0,0,0),float3(1,1,1),saturate(LightNormal*16+0.5)

saturate 函数,很好理解,saturate(x)将 x 的数值,截取在 0-1 之间。

接下来我们更改一下 LightNormal*16,从左到右依次是 * 32,*64。可以看到,边缘的强烈分割。

还有一个插值函数,smoothstep,作用和用法跟 lerp 一致,但两者之间有一定的区别,这里不多赘述,因为用不到。可以借鉴学习 https://blog.csdn.net/qq_41835314/article/details/128618789

最后一个问题,为什么要 LightNormal*16+0.5?

通过修改数值能够有所体会,若想究其原理,需要拿出纸笔,动手算算或者思考一下。

  1. 在球的光照亮面取一个点,边缘上取一个点,暗面取一个点。

  2. 用 float LightNormal = dot(Normal,-LightDirection)

分别算出 LightNormal 的正负,大小的排序。

3.saturate(LightNormal*16+0.5),取得三者权重,然后分别插值。

关于 HLSL 中的函数,这里就不搬运了,参考微软官方文档,或者参考 https://blog.csdn.net/eloudy/article/details/71258367

评论