定义
高光反射是一种经验模型,并不完全符合真实世界中的高光反射现象,用于计算那些沿着完全镜面反射方向被反射的光线,可以让物体看起来有光泽,比如金属材质。
计算高光反射需要知道 表面法线,视角方向,光源方向,反射方向等
公式
高光反射Specular = 直射光 * pow(max(0, cosθ), 高光反射参数)
θ = 反射光方向和视野方向的夹角
顶点计算/片元计算
效果
逐顶点计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
Shader "WCC/Specular"{ Properties { _Diffuse ("Diffuse", Color) = (1, 1, 1, 1) //控制高光反射颜色 _Specular ("Specular", Color) = (1, 1, 1, 1) //控制高光区域大小 _Gloss ("Gloss", Range(8.0, 256)) = 20 } SubShader { Pass { Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; fixed4 _Specular; float _Gloss; struct a2v { //模型空间的顶点坐标 float4 vertex:POSITION; //模型空间的法线方向 float3 normal:NORMAL; }; struct v2f { //输出的是裁剪空间的顶点坐标 float4 pos:SV_POSITION; float3 color:COLOR; }; v2f vert(a2v v){ v2f o; //利用unity内置的模型-观察-投影矩阵将顶点坐标转换到裁剪空间 o.pos=UnityObjectToClipPos(v.vertex); //通过内置变量获取环境光 fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz; //法线转换到世界坐标 //unity_WorldToObject为模型空间到世界空间的变换矩阵的逆矩阵 fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject)); //获取光源方向 fixed3 worldLight=normalize(_WorldSpaceLightPos0.xyz); //利用漫反射光照公式计算漫反射 fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*max(0,dot(worldNormal,worldLight)); //利用Cg内置反射光线方向计算函数计算反射光线 fixed3 reflectDir = normalize(reflect(-worldLight, worldNormal)); //mul(unity_ObjectToWorld, v.vertex)将顶点坐标转换为世界坐标 //视角方向=摄像头位置-顶点位置 fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz); //根据公式计算高光反射 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss); o.color=ambient + diffuse + specular; return o; } fixed4 frag(v2f f):SV_Target { return fixed4(f.color,1.0); } ENDCG } } FallBack "Specular" } |
逐片元计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
Shader "WCC/Specular Fragment"{ Properties { _Diffuse ("Diffuse", Color) = (1, 1, 1, 1) //控制高光反射颜色 _Specular ("Specular", Color) = (1, 1, 1, 1) //控制高光区域大小 _Gloss ("Gloss", Range(8.0, 256)) = 20 } SubShader { Pass { Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; fixed4 _Specular; float _Gloss; struct a2v { //模型空间的顶点坐标 float4 vertex:POSITION; //模型空间的法线方向 float3 normal:NORMAL; }; struct v2f { //输出的是裁剪空间的顶点坐标 float4 pos:SV_POSITION; float3 worldNormal:TEXCOORD0; float3 worldVertex:TEXCOORD1; }; v2f vert(a2v v){ v2f f; //利用unity内置的模型-观察-投影矩阵将顶点坐标转换到裁剪空间 f.pos=UnityObjectToClipPos(v.vertex); //法线转换到世界坐标 //unity_WorldToObject为模型空间到世界空间的变换矩阵的逆矩阵 f.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject); //mul(unity_ObjectToWorld, v.vertex)将顶点坐标转换为世界坐标 f.worldVertex=mul(unity_ObjectToWorld, v.vertex); return f; } fixed4 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)); //利用Cg内置反射光线方向计算函数计算反射光线 fixed3 reflectDir = normalize(reflect(-lightDir, normalDir)); //视角方向=摄像头位置-顶点位置 fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - f.worldVertex.xyz); //根据公式计算高光反射 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss); fixed3 color=ambient + diffuse + specular; return fixed4(color,1.0); } ENDCG } } FallBack "Specular" } |
- 本文固定链接: http://www.u3d8.com/?p=2613
- 转载请注明: 网虫虫 在 u3d8.com 发表过
[…] Shader高光反射Phong […]