记录一个URP中的带粗糙、高光、光泽度调节的shader,方便之后作为扩展的基础使用。
csharp
// OrenNayarURP.shader
Shader "Custom/OrenNayarURP"
{
Properties
{
[MainTexture] _BaseMap("Texture", 2D) = "white" {}
[MainColor] _BaseColor("Color", Color) = (1,1,1,1)
//粗糙
_Roughness("Roughness", Range(0, 1)) = 0.5
//高光
_Specular("Specular", Range(0, 1)) = 0.0
//光泽
_Gloss("Gloss", Range(0, 1)) = 0.5
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
"IgnoreProjector" = "True"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normalWS : TEXCOORD1;
float3 positionWS : TEXCOORD2;
float3 viewDirWS : TEXCOORD3;
};
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
float4 _BaseMap_ST;
CBUFFER_START(UnityPerMaterial)
float4 _BaseColor;
float _Roughness;
float _Specular;
float _Gloss;
CBUFFER_END
// Oren-Nayar BRDF 函数
float OrenNayarDiffuse(
float3 lightDir,
float3 viewDir,
float3 normal,
float roughness)
{
float NdotL = saturate(dot(normal, lightDir));
float NdotV = saturate(dot(normal, viewDir));
if (NdotL <= 0 || NdotV <= 0)
return 0.0;
float sigma = roughness * 1.570796; // π/2
float sigma2 = sigma * sigma;
float A = 1.0 - 0.5 * (sigma2 / (sigma2 + 0.33));
float B = 0.45 * (sigma2 / (sigma2 + 0.09));
float3 lightProj = normalize(lightDir - normal * NdotL);
float3 viewProj = normalize(viewDir - normal * NdotV);
float cosPhi = dot(lightProj, viewProj);
cosPhi = saturate(cosPhi);
float thetaL = acos(NdotL);
float thetaV = acos(NdotV);
float alpha = max(thetaL, thetaV);
float beta = min(thetaL, thetaV);
float L1 = A;
float L2 = B * cosPhi * sin(alpha) * tan(beta);
return NdotL * (L1 + L2);
}
Varyings vert(Attributes IN)
{
Varyings OUT;
VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
OUT.positionHCS = positionInputs.positionCS;
OUT.positionWS = positionInputs.positionWS;
VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS);
OUT.normalWS = normalInputs.normalWS;
OUT.viewDirWS = GetWorldSpaceNormalizeViewDir(OUT.positionWS);
OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
// 准备数据
float3 normalWS = normalize(IN.normalWS);
float3 viewDirWS = normalize(IN.viewDirWS);
// 获取主光源
Light mainLight = GetMainLight();
float3 lightDirWS = normalize(mainLight.direction);
// Oren-Nayar 漫反射
float diffuse = OrenNayarDiffuse(lightDirWS, viewDirWS, normalWS, _Roughness);
float3 diffuseColor = diffuse * mainLight.color * _BaseColor.rgb;
// 简单高光
float3 halfVec = normalize(lightDirWS + viewDirWS);
float specular = pow(saturate(dot(normalWS, halfVec)), _Gloss * 128) * _Specular;
float3 specularColor = specular * mainLight.color;
// 纹理采样
float4 texColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
// 组合颜色
float3 finalColor = (diffuseColor + specularColor) * texColor.rgb;
return half4(finalColor, 1.0);
}
ENDHLSL
}
}
}