我们在这篇文章中,了解一下URP中Shader怎么实现菲涅尔效果,同时学习一下URP下怎么获取法线 和 视线向量。
Lambert光照模型公式:
Diffuse = Ambient + Kd * LightColor * max(0,dot(N,L))
实现灯光照射中间亮 周围暗的效果,核心是dot(N,L)
光照效果下, 视线单位向量 点积 法线单位向量的效果是 中间亮周围暗。我们需要的效果刚好相反,用 1 减去该结果即可得到菲尼尔效果。
所以,我们主要要获取 N 和 L
我们在之前的文章中,实现过一次菲涅尔效果(模型中间暗周围亮的效果)
为什么 NdotL 可以得到中间亮,周围亮的的效果
我们这里用一个 BRP 下的Shader来修改为 URP 下的该效果
Shader "MyShader/URP/P3_2_4"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return 1;
}
ENDCG
}
}
}
“RenderPipeline” = “UniversalPipeline”
CGPROGRAM -> HLSLPROGRAM
ENDCG -> ENDHLSL
#include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl”
#include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
#include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
#include “Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl”
struct Attributes
{
float3 vertexOS : POSITION;
float3 normalOS : NORMAL;
};
struct Varyings
{
float4 vertexCS : SV_POSITION;
float3 normalWS : TEXCOORD0;
};
o.normalWS = TransformObjectToWorld(v.normalOS);
要获取该向量,需要知道 摄像机的世界空间坐标 和 我们顶点的世界空间坐标
_WorldSpaceCameraPos
float3 vertexWS : TEXCOORD1;
o.vertexWS = TransformObjectToWorld(v.vertexOS);
half3 L = normalize(_WorldSpaceCameraPos - i.vertexWS);
half NdotL = dot(N,L);
需要调节效果强弱的话,我们使用pow函数即可
return 1 - NdotL;
//URP下的菲涅尔效果
Shader "MyShader/URP/P3_2_4"
{
Properties
{
}
SubShader
{
Tags
{
//告诉引擎,该Shader只用于 URP 渲染管线
"RenderPipeline"="UniversalPipeline"
//渲染类型
"RenderType"="Opaque"
//渲染队列
"Queue"="Geometry"
}
Pass
{
Cull Back Blend One Zero ZTest LEqual ZWrite On
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float3 vertexOS : POSITION;
float3 normalOS : NORMAL;
};
struct Varyings
{
float4 vertexCS : SV_POSITION;
float3 normalWS : TEXCOORD0;
float3 vertexWS : TEXCOORD1;
};
Varyings vert (Attributes v)
{
Varyings o;
o.vertexWS = TransformObjectToWorld(v.vertexOS);
o.vertexCS = TransformWorldToHClip(o.vertexWS);
o.normalWS = TransformObjectToWorldNormal(v.normalOS);
return o;
}
half4 frag (Varyings i) : SV_Target
{
//菲涅尔效果 1 - dot(N,L)
half3 N = i.normalWS;
half3 L = normalize(_WorldSpaceCameraPos - i.vertexWS);
half NdotL = dot(N,L);
return 1 - NdotL;
}
ENDHLSL
}
}
}