Unity3D Shader之光照模型——理论与实践:用两种方式来实现漫反射Diffuse Reflection
来源:互联网 发布:冒险岛交易市场数据 编辑:程序博客网 时间:2024/05/16 15:58
漫反射原理解析
众所周知,漫反射即光线射到粗糙的物体表面时发生的反射现象,入射光线为平行光线,而出射光线为各个方向。光在空气中以直线传播,光线的反射也遵守物理规则。如下图所示:
图片来源于网络。
上图左侧入射方向的是平行光,反射光也是平行光,这种现象称为镜面反射。而左侧反射光不平行无规则的则为漫反射。
图片来源于网络。
上图左侧表示,入射光线与出射光线形成的夹角,被垂直于反射面的光线均分。上图右侧表示在圆弧或不规则表面时,反射平面为反射点的切线,此时反射点的法线为经过此点垂直于其切线的直线。
然而在图形处理中,实际情况是模型远远没有现实这么复杂,有的时候甚至想用简单的模型(甚至是完全平面的模型)来表现出复杂或是特殊材质的物体。对于漫反射而言,不可能真的去做出具有无数个顶点,表面具有极其细微的凹凸不平之处的模型,如果真这样做,无论是人力还是计算机的处理能力都是非常有限的。因此就要使用一定的算法来模拟漫反射。
根据反射的规则和实际生活情况可知,入射光线与反射光线的夹角越小,则反射强度越大。并且物体表面越粗糙,那么反射后的亮度越弱,这是因为粗糙的表面将光线反射到了各个地方去。因此,我们要模拟的就是:
- 反射规则:入射光线与反射光线的关系
- 光线逸散:反射后由物体表面粗糙的原因导致光线光线逸散,反射后光线亮度变低
结合上两点,在实际生活中观察到的漫反射现象是: 入射光线与法线的夹角越小,则反射后的光线亮度越大。于是便采用 入射光线与法线的点积来 来计算反射系数,因为点积的几何意义是:点积的值越大,则两个向量的方向越相近。
结合我前面的文章《Unity3D内建参数文档翻译与解析——Built-in shader variables》来使用两种不同的Shader形式实现漫反射。
可编程Shader实现方式
代码
Shader "Custom/DiffuseReflection"{ Properties { _Color("Color", Color) = (1,1,1,1) _MainTex("Texture", 2D) = "white" {} } SubShader { // 设定LightMode为ForwardBase,相关细节可以查看我之前的文章《Unity3D光照前置知识——Rendering Paths(渲染路径)及LightMode(光照模式)译解》 Tags{ "LightMode" = "ForwardBase" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" // 使用Unity3D的头文件"Lighting.cginc",包含有我们需要的光照参数 #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; half3 normal : NORMAL; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 diff : TEXCOORD1; float4 diffColor : TEXCOORD2; }; v2f vert(appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.uv; // 本例中将光照计算过程写在vert函数内,因为这样相比写在frag函数内更节约性能。不过当然效果肯定没有在frag内好。 // 计算物体法线(用来代表在物体上入射点处的法线)与光照方向的点积,得到漫反射系数diff,用来表示漫反射的光照衰减,并且保证其值大于0。 float diff = max(0, dot(v.normal, _WorldSpaceLightPos0.xyz)); // 利用系数计算光线衰减后的色值 o.diffColor = _LightColor0 * 2 * diff; return o; } sampler2D _MainTex; fixed4 _Color; fixed4 frag(v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv) * _Color; // 得到最终颜色 col.rgb = i.diffColor * col.rgb; return col; } ENDCG } }}
结果
Surface Shader实现方式
代码
surface shader是Unity3D特有的一种Shader编写形式,封装了许多光照相关的功能。以后会开坑细讲。
Shader "Custom/DiffuseReflection" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // 声明自定义光照函数名 #pragma surface surf DiffuseReflection #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; fixed4 _Color; // 自定义光照函数 half4 LightingDiffuseReflection(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) { half diff = max(0, dot(s.Normal, lightDir)); half3 c = s.Albedo * diff * _LightColor0.rgb * 2; return fixed4(c, s.Alpha); } void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse"}
结果
- Unity3D Shader之光照模型——理论与实践:用两种方式来实现漫反射Diffuse Reflection
- Unity3D 开发之shader教程(浅谈光照之漫反射diffuse)
- Unity Shader之自定义漫反射光照模型
- 【Unity Shaders】Diffuse Shading——创建一个自定义的diffuse lighting model(漫反射光照模型)
- Shader山下(二)光照模型——漫反射
- Unity Shader-兰伯特光照模型与Diffuse Shader
- Unity Shader-兰伯特光照模型与Diffuse Shader
- 一步步学shader系列(2):环境光照diffuse漫反射光照
- 【Unity Shaders】Diffuse Shading——漫反射光照改善技巧
- 漫反射(diffuse reflection)
- 问题六十八:着色模型(shading model)(1)——反射模型(reflection model)(2.1)——漫反射(diffuse reflection)
- Unity3d Shader光照模型
- HLSL实现漫反射光照模型
- HLSL实现漫反射光照模型
- 基本光照模型实现-漫反射
- Unity Shader入门精要笔记(九):Unity 的基础光照——漫反射的实现
- Unity3D Shader(8)——Vertex Shader(漫反射)
- 3.Unity_CG_Shader光照之——漫反射(lambert模型以及Half lambert模型)
- laravel项目云服务器linux部署
- 算法系列—广度优先搜索(BFS)
- Java中private、protected、public和default的区别
- 一年之中第几天
- 【GDOI2017模拟11.3】永恒的契约
- Unity3D Shader之光照模型——理论与实践:用两种方式来实现漫反射Diffuse Reflection
- 何恺明经典去雾算法
- settings.db 在androd 6.0上的变化
- Android系统启动——Zygote进程
- ROS(indigo) 语音工具 科大讯飞 百度 pocketsphinx julius rospeex 16.11.22更新 ROS中文语音
- 21、SSM框架-Mybatis多参数查询与列表查询不同方式实现(3)
- myeclipse 修改jsp模板
- jquery实现表格字段统计功能
- hibernate中对象的三种状态