【TA-霜狼_may-《百人计划》】基础渲染光照介绍(一
【TA-霜狼_may-《百人计划》】基础渲染光照介绍(一
完整代码块如下,从头到尾打一遍,感觉把之前的东西都串起来!没事翻出来看看!
Shader "Custom/100 learning/myOwnBaseShaser"
{
Properties
{
_Diffuse("Diffuse", Color) = (1,1,1,1)
_MainTex("Main Tex", 2D) = "white" {}
_Specular("Specular", Color) = (1,1,1,1)
_Gloss("Gloss", Range(1.0, 255)) = 20
_NormalMap("Normal Map", 2D) = "white" {}
_LocalNormalSild("Local Normal", Range(0,1)) = 0
_CubeMap("Enviroment Cube Map", Cube) ="" {}
_MipScale("Mip Scale", Range(0,10)) = 0
_EnvScale("Enviroment Scale", Range(0,1)) = 1
}
SubShader
{
Pass{
// 定义Tags
Tags{"LightingMode" = "FOrwardBase"}
CGPROGRAM
// 引入头文件
#include "Lighting.cginc"
// 定义函数
#pragma vertex vert
#pragma fragment frag
// 定义并接收对应变量
float4 _Diffuse;
float4 _Specular;
float _Gloss;
float _LocalNormalSild;
uniform sampler2D _NormalMap; uniform float4 _NormalMap_ST;
sampler2D _MainTex; float4 _MainTex_ST;
samplerCUBE _CubeMap;
float _MipScale;
float _EnvScale;
// 定义结构体
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT;
float2 texcoord0 : TEXCOORD0;
};
struct v2f{
float4 pos : SV_POSITION;
float3 worldNormal:NORMAL;
float2 uv0 : TEXCOORD0;
float3 normalDir : TEXCOORD1;
float3 tangentDir : TEXCOORD2;
float3 bitangentDir : TEXCOORD3;
float3 worldPos: TEXCOORD4;
};
v2f vert(a2v v){
v2f o;
o.uv0 = v.texcoord0;
o.pos = UnityObjectToClipPos(v.vertex);
// 将法线转换到世界空间
// 旧写法:o.worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
o.worldNormal = UnityObjectToWorldNormal(v.normal);
// 顶点位置转换到世界空间
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
// 计算法线、切线、副切线
o.normalDir = UnityObjectToWorldNormal(v.normal);
o.tangentDir = normalize(mul(unity_ObjectToWorld,float4(v.tangent.xyz,0.0)).xyz);
o.bitangentDir = normalize(cross(o.normalDir,o.tangentDir)*v.tangent.w);
return o;
}
fixed4 frag(v2f i): SV_Target{
float4 mainTex = tex2D(_MainTex, TRANSFORM_TEX(i.uv0,_MainTex));
// TBN转换矩阵
float3x3 tangentTransform = float3x3 (i.tangentDir, i.bitangentDir,i.normalDir);
// 环境光
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * _Diffuse * mainTex.rgb;
// 归一化光照方向
float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
// 再次归一化worldNormal
float3 worldNormal = normalize(i.worldNormal);
i.normalDir = worldNormal;
// 获取映射过的法线贴图数据
float3 normalLocal = UnpackNormal(tex2D(_NormalMap, TRANSFORM_TEX(i.uv0, _NormalMap)));
float3 normalWorld = normalize(mul(normalLocal.rgb, tangentTransform));
float3 finiNormal = lerp(worldNormal, normalWorld, _LocalNormalSild);
//计算漫反射lambert公式
float NdotL = max(0.0, dot(finiNormal, worldLight));
// 多余:float NdotLNormalTex = dot(finiNormal, worldLight);
// diffuse
float3 diffuse = lerp(ambient.rgb * _Diffuse.rgb * mainTex.rgb, _LightColor0.rgb * _Diffuse.rgb * mainTex.rgb,NdotL);
//=====Phong=====
// 计算反射方向R,worldLight表示光源方向,入射光线方向为-worldLight,通过reflect函数(入射方向,法线方向)
float3 reflectDir = normalize(reflect(-worldLight,finiNormal));
// 计算该像素对应位置(顶点计算过后传给像素经过插值后)finiNormalV,相机坐标-像素坐标
// 这个写在片元着色器中有点不太对float3 viewDir = normalize(UnityWorldSpaceViewDir(i.pos));
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
// 反射光方向与观察方向的夹角 dot(V,R)
float VdotR = max(0.0, dot(reflectDir, viewDir));
// 计算高光值,根据反射系数计算的反射值为pow(VdotR, Gloss)
float3 specular = _LightColor0.rgb * _Specular.rgb * pow(VdotR, _Gloss);
// 由此得到最终颜色
float3 color = ambient + diffuse + specular;
//=====Blinn-Phong=====
// 计算半角向量(光想方向+视角方向,结果归一化)
float3 halfDir = normalize(worldLight + viewDir);
// 半角向量与法线方向的夹角 dot(V,R)
float NdotH = saturate(dot(halfDir,finiNormal));
// 环境贴图
float3 worldRef = normalize(reflect(-viewDir, finiNormal));
float4 reflcol = texCUBElod( _CubeMap, float4(worldRef.rgb, (255-_Gloss)*8/(255))) * _EnvScale;
// 计算Specular (在Blinn-Phong下)
specular = _LightColor0.rgb * _Specular.rgb * pow(NdotH, _Gloss);
specular = lerp(diffuse * specular, specular, _Gloss/255);
reflcol.rgb = lerp(reflcol * diffuse.rgb, reflcol, _Gloss/255);
color =diffuse + reflcol.rgb + specular;
return fixed4(color.rgb,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}