【Unity Shaders】Diffuse Shading——使用2D ramp texture来创建一个假的BRDF(双向反射分布函数)
本系列主要参考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。
这里是本书所有的插图。这里是本书所需的代码和资源(当然你也可以从官网下载)。
========================================== 分割线 ==========================================
终于到了Diffuse Shading一章的最后一篇了!回忆一下,在上一篇中,一共学习了两种改善漫反射光照的方法:一种是完全根据感性认识,使用Half Lembert方法改变了光照值区间,使得物体颜色整体提亮;一种是通过一张渐变图,来控制光照值。
这两种方法都只考虑到了入射光线和反射点所在的平面法向量的夹角,但是想象实际生活中我们观察一个物体,即便是在相同的光照下观察物体的同一点,如果我们观察位置有所改变,看到的结果也会不一样。因此,这一篇中,我们将引入这一新的参数:view direction——观察点方向。
为了达到这一目的,我们使用一张二维的渐变图来代替之前的一维渐变图(因为在之前的方法中,我们仅使用一个参数就决定了该图的采样位置),使用两个参数来决定采样的真正的UV坐标:一个参数由入射光线和平面法向量计算而得,一个由观察点方向和平面法向量计算而得。
BRDF
准备工作
- 还是需要上一篇结束时的代码:
Shader "Custom/RampDiffuse" {
Properties {
_EmissiveColor ("Emissive Color", Color) = (1,1,1,1)
_AmbientColor ("Ambient Color", Color) = (1,1,1,1)
_MySliderValue ("This is a Slider", Range(0,10)) = 2.5
_RampTex ("Ramp Texture", 2D) = "white"{}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf BasicDiffuse float4 _EmissiveColor;
float4 _AmbientColor;
float _MySliderValue;
sampler2D _RampTex; struct Input
{
float2 uv_MainTex;
}; void surf (Input IN, inout SurfaceOutput o)
{
float4 c;
c = pow((_EmissiveColor + _AmbientColor), _MySliderValue);
o.Albedo = c.rgb;
o.Alpha = c.a;
} inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)
{
float difLight = max(0, dot (s.Normal, lightDir));
float hLambert = difLight * 0.5 + 0.5;
float3 ramp = tex2D(_RampTex, float2(hLambert)).rgb; float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (ramp);
col.a = s.Alpha;
return col;
} ENDCG
}
FallBack "Diffuse"
} - 除此之外,我们还需要一张二维渐变图:
大小为512*512:首先从左下角开始一个渐变色,直到图片右上角;再开始另一个渐变色,从左上角开始一直到图片中间;最后再开始一个渐变色,从右下角直到中间。
实现
- 首先,给我们的光照函数LightingBasicDiffuse添加新的参数viewDir,表示观察方向:
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
这个参数将会由Unity内部提供,来得到当前摄像机的观察位置到观察点的方向向量。
- 与计算入射光线和平面法向量类似,计算观察方向和平面法向量的夹角余弦值:
float rimLight = max(0, dot (s.Normal, viewDir));
- 使用Half Lambert方法改善rimLight的值(后面我们会对比一下如果不这么做会有什么区别):
float rim_hLambert = rimLight * 0.5 + 0.5;
- 最后,使用新的计算结果在_RampTex中采样:
float3 ramp = tex2D(_RampTex, float2(dif_hLambert, rim_hLambert)).rgb;
- 完成的代码如下:
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
float difLight = max(0, dot (s.Normal, lightDir));
// Add this line
float rimLight = max(0, dot (s.Normal, viewDir));
// Modify this line
float dif_hLambert = difLight * 0.5 + 0.5;
// Add this line
float rim_hLambert = rimLight * 0.5 + 0.5;
// Modify this line
float3 ramp = tex2D(_RampTex, float2(dif_hLambert, rim_hLambert)).rgb; float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (ramp);
col.a = s.Alpha;
return col;
} - 最后得到的渲染结果如下:
解释
思考
两个方向都不考虑max、不使用Half Lambert
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
float difLight = dot (s.Normal, lightDir);
float rimLight = dot (s.Normal, viewDir);
float3 ramp = tex2D(_RampTex, float2(difLight, rimLight)).rgb; float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (ramp);
col.a = s.Alpha;
return col;
}
渲染结果如下:
分别对两个方向使用max
float difLight = max (0, dot (s.Normal, lightDir));
结果如下:
float rimLight = max (0, dot (s.Normal, viewDir));
结果如下:
分别使用Half Lambert修正
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
float difLight = max (0, dot (s.Normal, lightDir));
float rimLight = max (0, dot (s.Normal, viewDir));
float dif_hLambert = difLight * 0.5 + 0.5;
float3 ramp = tex2D(_RampTex, float2(dif_hLambert, rimLight)).rgb; float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (ramp);
col.a = s.Alpha;
return col;
}
结果如下:
结束语
【Unity Shaders】Diffuse Shading——使用2D ramp texture来创建一个假的BRDF(双向反射分布函数)的更多相关文章
- 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建Cubemaps
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】概述及Diffuse Shading介绍
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】学习笔记——SurfaceShader(四)用纹理改善漫反射
[Unity Shaders]学习笔记——SurfaceShader(四)用纹理改善漫反射 转载请注明出处:http://www.cnblogs.com/-867259206/p/5603368.ht ...
- 【Unity Shaders】《Unity Shaders and Effects Cookbook》总结篇
我的唠叨 不知不觉,从发表第一篇关于<Unity Shaders and Effects Cookbook>已经快十个月了.一开始的初衷就是学习笔记,毕竟将来回过头去看的时候,再看英文难免 ...
- 【Unity Shaders】Diffuse Shading——漫反射光照改善技巧
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Diffuse Shading——向Surface Shader添加properties
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Diffuse Shading——创建一个基本的Surface Shader
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
随机推荐
- FJUT第四周寒假作业之第一集,临时特工?(深度优先搜索)
原网址:http://210.34.193.66:8080/vj/Contest.jsp?cid=163#P2 第一集,临时特工? TimeLimit:1000MS MemoryLimit:128M ...
- 【kmp】 剪花布条 HDU - 2087
[题意概述] [解题思路] 从左往右找,看有几个匹配的字符串,但要注意例如 aaaaaa aa的输出是3 而不是5,可以这样理解:画布需要减去,一旦减去也就没有了的 [AC] #include< ...
- CF | Alyona and Numbers
After finishing eating her bun, Alyona came up with two integers n and m. She decided to write down ...
- lglob-lua 静态检查脚本
./lglob ~/ngx/lualib/mvc/*.lua 2>&1 | grep ' set '
- NLP系列(5)_从朴素贝叶斯到N-gram语言模型
作者: 龙心尘 && 寒小阳 时间:2016年2月. 出处: http://blog.csdn.net/longxinchen_ml/article/details/50646528 ...
- ubuntu重装指定版本的mysql
查看错误log cat /var/log/mysql/error.log 首先彻底删除mysql,比如版本5.5 apt-get autoremove --purge mysql-server-5.5 ...
- Eclipse调试(1)——基础篇
作为使用Eclipse的程序员都会使用它的Debug.但是有不少人只会用F6.F8,其他功能知之甚少.今天我就来总结一下我在使用eclipse的debug时的一些个人经验.水平有限,不足之处还请赐教. ...
- Shell脚本了解
一.什么是Shell Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面, ...
- Android新特性Instant Run详解
关于 Instant Run Android Studio 2.0 中引入的 Instant Run 是 Run 和 Debug 命令的行为,可以大幅缩短应用更新的时间.尽管首次构建可能需要花费较长的 ...
- Dynamics CRM2016 升级老版本报“JavaScript Web 资源包含对 Microsoft Dynamics CRM 4.0 (2007) Web 服务终结点的引用”问题的解决办法
今天在新的服务器上部署了CRM2016 on-premises,并将CRM2015的数据库拷贝过来准备附加后升级,但在升级过程中遇到了如下错误,向导检测到了我的JavaScript Web 资源中包含 ...