本文主要是介绍庄懂着色器_L08_OldSchoolPlus/Normal,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
庄懂-BoyanTata的个人空间_哔哩哔哩_Bilibili
答疑
ShaderFeature 用到才会编译分支
MultiCompile 用不用到都会编译分支
作业回顾
OldSchool Plus代码
_EnvUpCol 环境天顶颜色
_EnvSideCol 环境水平颜色
_EnvDownCol 环境地表颜色
Shader "AP01/L08/OldSchoolPlus"
{Properties{_BaseCol ("基本色", Color) = (0.5, 0.5, 0.5, 1.0)_LightCol ("光颜色", Color) = (1.0, 1.0, 1.0, 1.0)_SpecPow ("高光次幂", Range(1, 90)) = 30_Occlusion ("AO图", 2D) = "white" {}_EnvInt ("环境光强度", Range(0, 1)) = 0.2_EnvUpCol ("环境天顶颜色", Color) = (1.0, 1.0, 1.0, 1.0)_EnvSideCol ("环境水平颜色", Color) = (0.5, 0.5, 0.5, 1.0)_EnvDownCol ("环境地表颜色", Color) = (0.0, 0.0, 0.0, 0.0)}SubShader{Tags { "RenderType"="Opaque" }Pass{Name "FORWARD"Tags { "LightMode"="ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"// 追加投影相关包含文件#include "AutoLight.cginc"#include "Lighting.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma target 3.0// 输入参数uniform float3 _BaseCol;uniform float3 _LightCol;uniform float _SpecPow;uniform sampler2D _Occlusion;uniform float _EnvInt;uniform float3 _EnvUpCol;uniform float3 _EnvSideCol;uniform float3 _EnvDownCol;// 输入结构struct VertexInput{float4 vertex : POSITION; // 顶点信息 Get✔float4 normal : NORMAL; // 法线信息 Get✔float2 uv0 : TEXCOORD0; // UV信息 Get✔};// 输出结构struct VertexOutput{float4 pos : SV_POSITION; // 裁剪空间(暂理解为屏幕空间吧)顶点位置float2 uv0 : TEXCOORD0; // UV0float4 posWS : TEXCOORD1; // 世界空间顶点位置float3 nDirWS : TEXCOORD2; // 世界空间法线方向LIGHTING_COORDS(3,4) // 投影相关};// 输入结构>>>顶点Shader>>>输出结构VertexOutput vert (VertexInput v){VertexOutput o = (VertexOutput)0; // 新建输出结构o.pos = UnityObjectToClipPos( v.vertex ); // 变换顶点位置 OS>CSo.uv0 = v.uv0; // 传递UVo.posWS = mul(unity_ObjectToWorld, v.vertex); // 变换顶点位置 OS>WSo.nDirWS = UnityObjectToWorldNormal(v.normal); // 变换法线方向 OS>WSTRANSFER_VERTEX_TO_FRAGMENT(o) // 投影相关return o; // 返回输出结构}// 输出结构>>>像素float4 frag(VertexOutput i) : COLOR{// 准备向量float3 nDir = normalize(i.nDirWS);float3 lDir = _WorldSpaceLightPos0.xyz;float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);float3 rDir = reflect(-lDir, nDir);// 准备点积结果float ndotl = dot(nDir, lDir);float vdotr = dot(vDir, rDir);// 光照模型(直接光照部分)float shadow = LIGHT_ATTENUATION(i); // 获取投影float lambert = max(0.0, ndotl);float phong = pow(max(0.0, vdotr), _SpecPow);float3 dirLighting = (_BaseCol * lambert + phong) * _LightCol * shadow;// 光照模型(环境光照部分)float upMask = max(0.0, nDir.g); // 获取朝上部分遮罩float downMask = max(0.0, -nDir.g); // 获取朝下部分遮罩float sideMask = 1.0 - upMask - downMask; // 获取侧面部分遮罩// 混合环境色float3 envCol = _EnvUpCol * upMask + _EnvSideCol * sideMask + _EnvDownCol * downMask;float occlusion = tex2D(_Occlusion, i.uv0); // 采样Occlusion贴图float3 envLighting = envCol * _EnvInt * occlusion; // 计算环境光照// 返回结果float3 finalRGB = dirLighting + envLighting;return float4(finalRGB, 1.0);}ENDCG}}FallBack "Diffuse"
}
作业范例批改
法线贴图Normal_连连看部分
不能撇开空间,去谈方向
TBN矩阵的作用
将 切线空间下的法线信息变换到世界空间才能和光向量去点乘
代码部分
Shader "AP01/L08/NormalMap"
{Properties{_NormalMap ("法线贴图", 2D) = "bump" {}}SubShader{Tags { "RenderType"="Opaque" }Pass{Name "FORWARD"Tags { "LightMode"="ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma target 3.0// 输入参数uniform sampler2D _NormalMap;// 输入结构struct VertexInput{float4 vertex : POSITION; // 顶点信息float2 uv0 : TEXCOORD0; // 需要UV坐标 采样法线贴图float4 normal : NORMAL; // 法线信息float4 tangent : TANGENT; // 构建TBN矩阵 需要模型切线信息};// 输出结构struct VertexOutput{float4 pos : SV_POSITION;float2 uv0 : TEXCOORD0; // UV信息float3 nDirWS : TEXCOORD1; // 世界空间法线信息float3 tDirWS : TEXCOORD2; // 世界空间切线信息float3 bDirWS : TEXCOORD3; // 世界空间切线信息};// 输入结构>>>顶点Shader>>>输出结构VertexOutput vert (VertexInput v){VertexOutput o = (VertexOutput)0; // 新建一个输出结构o.pos = UnityObjectToClipPos( v.vertex ); // 变换顶点信息 并将其塞给输出结构o.uv0 = v.uv0; // 传递UV信息o.nDirWS = UnityObjectToWorldNormal(v.normal); // 世界空间法线信息o.tDirWS = normalize(mul( unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz); // 世界空间切线信息o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w); // 世界空间切线信息return o; // 将输出结构 输出}// 输出结构>>>像素float4 frag(VertexOutput i) : COLOR{// 获取nDirfloat3 nDirTS = UnpackNormal(tex2D(_NormalMap, i.uv0)).rgb; // 采样法线纹理并解码 切线空间nDirfloat3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS); // 构建TBN矩阵float3 nDirWS = normalize(mul(nDirTS, TBN)); // 世界空间nDir// 获取lDirfloat3 lDir = _WorldSpaceLightPos0.xyz;// 一般Lambertfloat nDotl = dot(nDirWS, lDir); // nDir点积lDirfloat lambert = max(0.0, nDotl); // 截断负值return float4(lambert, lambert, lambert, 1.0); // 输出最终颜色}ENDCG}}FallBack "Diffuse"
}
这篇关于庄懂着色器_L08_OldSchoolPlus/Normal的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!