Unity Shader 入门精要(03) -- Unity的基础光照
发布日期:2021-06-29 11:13:26
浏览次数:3
分类:技术文章
本文共 6037 字,大约阅读时间需要 20 分钟。
一、什么是光照模型
光照模型就是一个公式,使用这个公式来计算在某个点的光照效果
二、标准光照模型
在标准光照模型里面,我们把进入摄像机的光分为下面四个部分
自发光:光源散发的光。 高光反射 :光源照射到模型表面时,该表面会在完全镜面反射方向散射。 Blinn光照模型:Specular=直射光 * pow( max(cosθ,0),10) θ:是反射光方向和视野方向的夹角 Blinn-Phong光照模型:Specular=直射光 * pow( max(cosθ,0),10) θ:是法线和x的夹角 x 是平行光和视野方向的平分线 漫反射:光源照射到模型表面时,该表面会想买个防线散射。 Diffuse = 直射光颜色 * max(0,cos夹角(光和法线的夹角) ) 环境光:其他所有间接光照。三、光照模型的实现
兰伯特光照模型:在光照无法到达的区域,模型外观通常是全黑的。如背面没有明暗的变化,失去模型细节变化。
Diffuse = 直射光颜色 * max(0,cos夹角(光和法线的夹角) ) cosθ = 光方向· 法线方向 半兰伯特光照模型: Diffuse = 直射光颜色 *( cosθ *0.5 +0.5 )//兰伯特逐片元光照Shader "Custom/Chapter 5/03_Diffuse1" { Properties { _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0) //材质的漫反射颜色 } SubShader{ Pass{ //只有定义了正确的LightMode才能得到一些Unity的内置光照变量 Tags{ "LightMode"="ForwardBase" } CGPROGRAM #include "Lighting.cginc" //包含unity的内置的文件,才可以使用unity内置的一些变量 #pragma vertex vert //顶点着色器 #pragma fragment frag //片元着色器 //在Cg代码中,与属性名称和类型都匹配 fixed4 _Diffuse; //application to vertex struct a2v{ float4 vertex:POSITION; //模型顶点坐标 float3 normal:NORMAL; //法线 计算光照 }; // struct v2f{ float4 pos:SV_POSITION; float3 color:COLOR0; }; v2f vert(a2v v){ v2f f; //声明输出结构 f.pos = UnityObjectToClipPos (v.vertex);//把顶点坐标从模型空间转换到剪裁空间 //环境光 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 normalDir = normalize( mul(v.normal, (float3x3)unity_WorldToObject)); //法线转换到世界空间 fixed3 lightDir = normalize( _WorldSpaceLightPos0.xyz); //对于每个顶点,取得平行光世界空间下的位置(方向). fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot( normalDir, lightDir)); //得到漫反射的颜色 f.color = ambient + diffuse; return f; //传递给片元着色器 } float4 frag(v2f f) : SV_Target{ return fixed4(f.color, 1); } ENDCG } } FallBack "Diffuse"}
//兰伯特逐像素光照Shader "Custom/Chapter 5/03_Diffuse2" { Properties { _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0) } SubShader{ Pass{ Tags{ "LightMode"="ForwardBase" } CGPROGRAM #include "Lighting.cginc" #pragma vertex vert //顶点着色器 #pragma fragment frag //片元着色器 //在Cg代码中,与属性名称和类型都匹配 fixed4 _Diffuse; //application to vertex struct a2v{ float4 vertex:POSITION; //模型顶点坐标 float3 normal:NORMAL; //法线 计算光照 }; // struct v2f{ float4 pos:SV_POSITION; float3 worldNormal:TEXCOORD0; }; v2f vert(a2v v){ v2f f; //声明输出结构 f.pos = UnityObjectToClipPos (v.vertex);//把顶点坐标从模型空间转换到剪裁空间 f.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject); //法线转换到世界空间 return f; //传递给片元着色器 } float4 frag(v2f f) : SV_Target{ //环境光 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 normalDir = normalize(f.worldNormal); //法线转换到世界空间 fixed3 lightDir = normalize( _WorldSpaceLightPos0.xyz); //对于每个顶点,取得平行光世界空间下的位置(方向). fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot( normalDir, lightDir)); //得到漫反射的颜色 fixed3 color = ambient + diffuse; return fixed4(color, 1); } ENDCG } } FallBack "Diffuse"}
//半兰伯特光照模型 + BlinnPhong光照模型Shader "Custom/Chapter 6/06_Specular Fragment BlinnPhong" { Properties { _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0) //材质的漫反射颜色 _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0) //材质的高光反射颜色 _Gloss("Gloss", Range(2, 256)) = 20 //控制高光区域的大小 } SubShader{ Pass{ //只有定义了正确的LightMode才能得到一些Unity的内置光照变量 _LightColor0 Tags{ "LightMode"="ForwardBase" } CGPROGRAM #include "Lighting.cginc" //包含unity的内置的文件,才可以使用unity内置的一些变量 _LightColor0 #pragma vertex vert //顶点着色器 #pragma fragment frag //片元着色器 //在Cg代码中,与属性名称和类型都匹配 (0-1)使用 fixed精度的变量存储 _Gloss的变化范围大,使用float精度存储 fixed4 _Diffuse; fixed4 _Specular; float _Gloss; //application to vertex struct a2v{ float4 vertex:POSITION; //模型顶点坐标 float3 normal:NORMAL; //法线 计算光照 }; // struct v2f{ float4 pos:SV_POSITION; float3 worldNormal:TEXCOORD0; float3 worldPos:TEXCOORD1; }; v2f vert(a2v v){ v2f f; //声明输出结构 f.pos = UnityObjectToClipPos (v.vertex);//把顶点坐标从模型空间转换到剪裁空间 f.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject); //法线转换到世界空间 f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; //世界空间下的顶点坐标 return f; //传递给片元着色器 } float4 frag(v2f f) : SV_Target{ //环境光 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 normalDir = normalize(f.worldNormal); //法线转换到世界空间 fixed3 lightDir = normalize( _WorldSpaceLightPos0.xyz); //对于每个顶点,取得平行光世界空间下的位置(方向). fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot( normalDir, lightDir)); //得到漫反射的颜色 //fixed3 reflectDir = normalize(reflect(-lightDir, normalDir)); fixed3 viewDir = normalize(_WorldSpaceLightPos0.xyz - f.worldPos.xyz); fixed3 halfDir = normalize(normalDir + viewDir); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot( normalDir, halfDir)), _Gloss);//得到高光反射的颜色 fixed3 color = ambient + diffuse + specular; return fixed4(color, 1); } ENDCG } } FallBack "Diffuse"}
转载地址:https://blog.csdn.net/zwg739424406/article/details/81875813 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
逛到本站,mark一下
[***.202.152.39]2024年04月22日 02时09分36秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
「第四篇」电赛控制题可以准备一些什么?
2019-04-29
「第五篇」全国电子设计竞赛-电源题设计方案总结
2019-04-29
「第六篇」对于电赛,我们应该看重什么?
2019-04-29
树莓派翻车了
2019-04-29
垃圾分类背后的数据和真相
2019-04-29
PID算法搞不懂?看这篇文章就够了。
2019-04-29
这位电子工程师,你不能错过。
2019-04-29
十八般武艺教你如何解决问题
2019-04-29
「权威发布」2019年大学生电子设计竞赛,仪器设备和主要元器件清单
2019-04-29
「重磅猜题之第二篇」2019年大学生电子设计竞赛
2019-04-29
知乎:硬件和软件哪个吃香?
2019-04-29
中国深圳,600架无人机的盛典!
2019-04-29
干货分享 JVM 之第 3 篇 —— Java 内存结构相关
2019-04-29
干货分享 JVM 之第 5 篇 —— 类加载器
2019-04-29
干货分享 JVM 之第 6 篇 —— SpringBoot2.0 框架性能调优
2019-04-29
基于 Hystrix 高并发服务限流第 1 篇 —— 必须了解的相关概念
2019-04-29
基于 Hystrix 高并发服务限流第 2 篇 —— 服务隔离(线程池隔离、信号量隔离)
2019-04-29
基于 Hystrix 高并发服务限流第 3 篇 —— 服务熔断、服务降级
2019-04-29