Unity URP多光源支持,多光源阴影投射,多光源阴影接收(优化版)
目录
前言:
一、属性
二、SubShader
三、ForwardLitPass
定义Tags
声明变体
声明变量
定义结构体
顶点Shader
片元Shader
四、全代码
四、添加官方的LitShader代码
五、全代码
六、效果图
七、结语
前言:
哈喽啊,我又来啦。这次呢给大家带来了UnityURP渲染管线的优化自定义多光源Shader模板,之前呢我也写过Unity URPShader支持多光源处理_urp 多光源-CSDN博客和多光源的阴影接收Unity URP支持多光源阴影_urp 多光源 阴影-CSDN博客。
前面的文章确实解决了很多,但是呢,其中硬要抠细节,说实话并不好,这次呢,我会给大家带来参考Unity官方的模板,重写URP管线里的Lit光照Shader,这个Shader在主要的光照部分能完美的处理,并且能够自定义我们想要的其它额外效果(主要是跟大家完美解决URP的阴影问题啦。)
其实呢,要改的东西不多,大多数都是Copy官方的Lit代码,其中我们核心修改“ForwardLit”部分。
(支持Sprite精灵图的阴影)
一、属性
Properties
{
[MainTexture] _BaseMap ("Albedo", 2D) = "white" { }
[MainColor] _BaseColor ("Color", Color) = (1, 1, 1, 1)
[Toggle] _ReceiveShadows ("Receive Shadows", Float) = 1.0
[Enum(UnityEngine.Rendering.CullMode)]_Cull ("CullMode", Float) = 2.0
[Toggle] _AlphaTest ("AlphaClip", Float) = 1.0
// ObsoleteProperties
[HideInInspector] _MainTex ("BaseMap", 2D) = "white" { }
[HideInInspector]_Smoothness ("Smoothness", Range(0.0, 1.0)) = 0.5
[HideInInspector]_Metallic ("Metallic", Range(0.0, 1.0)) = 0.0
[HideInInspector]_Cutoff ("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
}
属性呢就可以直接采用我写好的属性,这些都迎合了SRPBactcher,可以保留的最少的属性(奇迹上也不是真的最少啦,我的这种是最有用但最少的哈哈。)
二、SubShader
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "Lit" }
LOD 300
我们声明好Tags,当然可以根据你的项目需求,自定义这部分。
三、ForwardLitPass
定义Tags
这一块是我们的核心功能,我会给出多光源光照、多光源阴影接收的模板代码并解释,你可以根据需求任意修改它们。
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "Lit" }
LOD 300
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Blend One Zero, One Zero
ZWrite On
Cull[_Cull]
AlphaToMask On
}
}
声明变体
首先呢,Pass里的Name也不是固定的,可以随意修改它,这里我就默认了。
其次,这个Pass采用前向渲染的光照Tag,我们需要定义好。
然后是Blend部分,其实这里呢不加也可以,如果你操作的是透明物体,那么需要加上。
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local _RECEIVESHADOWS_ON //是否开启接收阴影的开关
#pragma shader_feature_local _ALPHATEST_ON //其否其余AlphaClip的开关【适合Png图片剔除】
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN //主光的阴影变体
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //额外光变体
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS //额外光的阴影变体
#pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH //阴影的质量变体
#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.universal/ShaderLibrary/ShaderGraphFunctions.hlsl" //主要用于后面的函数调用
声明变量
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
//CBuffer里的变量必须包含以下的变量,不然不会适配SRP,定义这些不会影响性能
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float4 _DetailAlbedoMap_ST;
half4 _BaseColor;
half4 _SpecColor;
half4 _EmissionColor;
half _Cutoff;
half _Smoothness;
half _Metallic;
half _BumpScale;
half _Parallax;
half _OcclusionStrength;
half _ClearCoatMask;
half _ClearCoatSmoothness;
half _DetailAlbedoMapScale;
half _DetailNormalMapScale;
half _Surface;
CBUFFER_END
//实例化参数,看需求定义
#ifdef UNITY_DOTS_INSTANCING_ENABLED
UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
UNITY_DOTS_INSTANCED_PROP(float4, _BaseColor)
UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
#endif
定义结构体
struct Attributes
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
float3 normalOS : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionHS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD1;
float3 normalWS : TEXCOORD2;
half3 lightColor : COLOR; //额外光照的颜色,需要进行记录顶点光照的
#ifdef _RECEIVESHADOWS_ON //开启接收光照开关需要的变量
float4 shadowCoord : TEXCOORD3; //主光的阴影
#ifdef _ADDITIONAL_LIGHTS
float4 shadowMask : TEXCOORD4; //如果是逐像素光源,需要一个shadowMask
#endif
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
顶点Shader
Varyings vert(Attributes v)
{
Varyings o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
o.positionHS = TransformObjectToHClip(v.positionOS.xyz);
o.positionWS = TransformObjectToWorld(v.positionOS.xyz);
o.normalWS = TransformObjectToWorldNormal(v.normalOS);
o.uv = v.texcoord;
//光照
o.lightColor = 0.0;
#ifdef _RECEIVESHADOWS_ON //如果开启接收阴影
//主光阴影坐标
o.shadowCoord = TransformWorldToShadowCoord(o.positionWS);
//多光源的阴影,需要定义shadowMask
#if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
half4 shadowMask = inputData.shadowMask;
#elif !defined(LIGHTMAP_ON)
half4 shadowMask = unity_ProbesOcclusion;
#else
half4 shadowMask = 1.0;
#endif
//如果是逐顶点灯光
#if _ADDITIONAL_LIGHTS_VERTEX
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, positionWS, shadowMask);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
o.lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
}
//如果是逐像素灯光
#elif _ADDITIONAL_LIGHTS
o.shadowMask = shadowMask;
#endif
//不开启接收阴影
#else
#ifdef _ADDITIONAL_LIGHTS_VERTEX
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, positionWS);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
o.lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
}
#endif
#endif
return o;
}
片元Shader
half4 frag(Varyings i) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(i);
//光照
half3 lightColor = i.lightColor; //如果是逐顶点光照,lightColor需要保存逐顶点的光照
//开启接受阴影
#ifdef _RECEIVESHADOWS_ON
//主光颜色和阴影
Light main_light = GetMainLight(i.shadowCoord);
half3 main_attenuatedLightColor = main_light.color * main_light.distanceAttenuation * main_light.shadowAttenuation;
lightColor += LightingLambert(main_attenuatedLightColor, main_light.direction, i.normalWS);
//如果是逐像素光源
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz, i.shadowMask);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
//继续累加颜色
lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
}
#endif
//不接受阴影
#else
Light main_light = GetMainLight();
half3 main_attenuatedLightColor = main_light.color * main_light.distanceAttenuation * main_light.shadowAttenuation;
lightColor += LightingLambert(main_attenuatedLightColor, main_light.direction, i.normalWS);
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
}
#endif
#endif
//环境光
half3 ambient = half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
//贴图基础颜色
half4 col = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
col.rgb *= _BaseColor.rgb * lightColor + ambient;
//alpha剔除,适配png图片
#ifdef _ALPHATEST_ON
col.a = AlphaDiscard(col.a, _Cutoff);
#else
col.a = 1.0;
#endif
return col;
}
四、全代码
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Blend One Zero, One Zero
ZWrite On
Cull[_Cull]
AlphaToMask On
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local _RECEIVESHADOWS_ON
#pragma shader_feature_local _ALPHATEST_ON
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
#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.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float4 _DetailAlbedoMap_ST;
half4 _BaseColor;
half4 _SpecColor;
half4 _EmissionColor;
half _Cutoff;
half _Smoothness;
half _Metallic;
half _BumpScale;
half _Parallax;
half _OcclusionStrength;
half _ClearCoatMask;
half _ClearCoatSmoothness;
half _DetailAlbedoMapScale;
half _DetailNormalMapScale;
half _Surface;
CBUFFER_END
#ifdef UNITY_DOTS_INSTANCING_ENABLED
UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
UNITY_DOTS_INSTANCED_PROP(float4, _BaseColor)
UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
#endif
struct Attributes
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
float3 normalOS : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionHS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD1;
float3 normalWS : TEXCOORD2;
half3 lightColor : COLOR;
#ifdef _RECEIVESHADOWS_ON
float4 shadowCoord : TEXCOORD3;
#ifdef _ADDITIONAL_LIGHTS
float4 shadowMask : TEXCOORD4;
#endif
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
Varyings vert(Attributes v)
{
Varyings o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
o.positionHS = TransformObjectToHClip(v.positionOS.xyz);
o.positionWS = TransformObjectToWorld(v.positionOS.xyz);
o.normalWS = TransformObjectToWorldNormal(v.normalOS);
o.uv = v.texcoord;
//光照
o.lightColor = 0.0;
#ifdef _RECEIVESHADOWS_ON
o.shadowCoord = TransformWorldToShadowCoord(o.positionWS);
//多光源的阴影
#if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
half4 shadowMask = inputData.shadowMask;
#elif !defined(LIGHTMAP_ON)
half4 shadowMask = unity_ProbesOcclusion;
#else
half4 shadowMask = 1.0;
#endif
#if _ADDITIONAL_LIGHTS_VERTEX
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, positionWS, shadowMask);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
o.lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
}
#elif _ADDITIONAL_LIGHTS
o.shadowMask = shadowMask;
#endif
#else
#ifdef _ADDITIONAL_LIGHTS_VERTEX
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, positionWS);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
o.lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
}
#endif
#endif
return o;
}
half4 frag(Varyings i) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(i);
//光照
half3 lightColor = i.lightColor;
#ifdef _RECEIVESHADOWS_ON
Light main_light = GetMainLight(i.shadowCoord);
half3 main_attenuatedLightColor = main_light.color * main_light.distanceAttenuation * main_light.shadowAttenuation;
lightColor += LightingLambert(main_attenuatedLightColor, main_light.direction, i.normalWS);
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz, i.shadowMask);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
}
#endif
#else
Light main_light = GetMainLight();
half3 main_attenuatedLightColor = main_light.color * main_light.distanceAttenuation * main_light.shadowAttenuation;
lightColor += LightingLambert(main_attenuatedLightColor, main_light.direction, i.normalWS);
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
}
#endif
#endif
//环境光
half3 ambient = half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
half4 col = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
col.rgb *= _BaseColor.rgb * lightColor + ambient;
#ifdef _ALPHATEST_ON
col.a = AlphaDiscard(col.a, _Cutoff);
#else
col.a = 1.0;
#endif
return col;
}
ENDHLSL
}
四、添加官方的LitShader代码
如果需要自定义阴影,可以看我之前的阴影部分文章的ShadowCast部分
Unity URP支持多光源阴影_urp 多光源 阴影-CSDN博客
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
// -------------------------------------
// Render State Commands
ZWrite On
ZTest LEqual
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Universal Pipeline keywords
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
ENDHLSL
}
Pass
{
// Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with
// no LightMode tag are also rendered by Universal Render Pipeline
Name "GBuffer"
Tags { "LightMode" = "UniversalGBuffer" }
// -------------------------------------
// Render State Commands
ZWrite[_ZWrite]
ZTest LEqual
Cull[_Cull]
HLSLPROGRAM
#pragma target 4.5
// Deferred Rendering Path does not support the OpenGL-based graphics API:
// Desktop OpenGL, OpenGL ES 3.0, WebGL 2.0.
#pragma exclude_renderers gles3 glcore
// -------------------------------------
// Shader Stages
#pragma vertex LitGBufferPassVertex
#pragma fragment LitGBufferPassFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local_fragment _ALPHATEST_ON
//#pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON
#pragma shader_feature_local_fragment _EMISSION
#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature_local_fragment _OCCLUSIONMAP
#pragma shader_feature_local _PARALLAXMAP
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
#pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF
#pragma shader_feature_local_fragment _SPECULAR_SETUP
#pragma shader_feature_local _RECEIVE_SHADOWS_OFF
// -------------------------------------
// Universal Pipeline keywords
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
//#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
#pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
#pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
#pragma multi_compile_fragment _ _RENDER_PASS_ENABLED
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"
// -------------------------------------
// Unity defined keywords
#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
#pragma multi_compile _ SHADOWS_SHADOWMASK
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DYNAMICLIGHTMAP_ON
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma instancing_options renderinglayer
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitGBufferPass.hlsl"
ENDHLSL
}
Pass
{
Name "DepthOnly"
Tags { "LightMode" = "DepthOnly" }
// -------------------------------------
// Render State Commands
ZWrite On
ColorMask R
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
ENDHLSL
}
// This pass is used when drawing to a _CameraNormalsTexture texture
Pass
{
Name "DepthNormals"
Tags { "LightMode" = "DepthNormals" }
// -------------------------------------
// Render State Commands
ZWrite On
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex DepthNormalsVertex
#pragma fragment DepthNormalsFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local _PARALLAXMAP
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
// -------------------------------------
// Universal Pipeline keywords
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlsl"
ENDHLSL
}
// This pass it not used during regular rendering, only for lightmap baking.
Pass
{
Name "Meta"
Tags { "LightMode" = "Meta" }
// -------------------------------------
// Render State Commands
Cull Off
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex UniversalVertexMeta
#pragma fragment UniversalFragmentMetaLit
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _SPECULAR_SETUP
#pragma shader_feature_local_fragment _EMISSION
#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
#pragma shader_feature_local_fragment _SPECGLOSSMAP
#pragma shader_feature EDITOR_VISUALIZATION
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitMetaPass.hlsl"
ENDHLSL
}
Pass
{
Name "Universal2D"
Tags { "LightMode" = "Universal2D" }
// -------------------------------------
// Render State Commands
Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex vert
#pragma fragment frag
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/Utils/Universal2D.hlsl"
ENDHLSL
}
五、全代码
Shader "Custom_Lit"
{
Properties
{
[MainTexture] _BaseMap ("Albedo", 2D) = "white" { }
[MainColor] _BaseColor ("Color", Color) = (1, 1, 1, 1)
[Toggle] _ReceiveShadows ("Receive Shadows", Float) = 1.0
[Enum(UnityEngine.Rendering.CullMode)]_Cull ("CullMode", Float) = 2.0
[Toggle] _AlphaTest ("AlphaClip", Float) = 1.0
// ObsoleteProperties
[HideInInspector] _MainTex ("BaseMap", 2D) = "white" { }
[HideInInspector]_Smoothness ("Smoothness", Range(0.0, 1.0)) = 0.5
[HideInInspector]_Metallic ("Metallic", Range(0.0, 1.0)) = 0.0
[HideInInspector]_Cutoff ("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
}
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "Lit" }
LOD 300
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Blend One Zero, One Zero
ZWrite On
Cull[_Cull]
AlphaToMask On
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local _RECEIVESHADOWS_ON
#pragma shader_feature_local _ALPHATEST_ON
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
#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.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float4 _DetailAlbedoMap_ST;
half4 _BaseColor;
half4 _SpecColor;
half4 _EmissionColor;
half _Cutoff;
half _Smoothness;
half _Metallic;
half _BumpScale;
half _Parallax;
half _OcclusionStrength;
half _ClearCoatMask;
half _ClearCoatSmoothness;
half _DetailAlbedoMapScale;
half _DetailNormalMapScale;
half _Surface;
CBUFFER_END
#ifdef UNITY_DOTS_INSTANCING_ENABLED
UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
UNITY_DOTS_INSTANCED_PROP(float4, _BaseColor)
UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
#endif
struct Attributes
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
float3 normalOS : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionHS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD1;
float3 normalWS : TEXCOORD2;
half3 lightColor : COLOR;
#ifdef _RECEIVESHADOWS_ON
float4 shadowCoord : TEXCOORD3;
#ifdef _ADDITIONAL_LIGHTS
float4 shadowMask : TEXCOORD4;
#endif
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
Varyings vert(Attributes v)
{
Varyings o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
o.positionHS = TransformObjectToHClip(v.positionOS.xyz);
o.positionWS = TransformObjectToWorld(v.positionOS.xyz);
o.normalWS = TransformObjectToWorldNormal(v.normalOS);
o.uv = v.texcoord;
//光照
o.lightColor = 0.0;
#ifdef _RECEIVESHADOWS_ON
o.shadowCoord = TransformWorldToShadowCoord(o.positionWS);
//多光源的阴影
#if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
half4 shadowMask = inputData.shadowMask;
#elif !defined(LIGHTMAP_ON)
half4 shadowMask = unity_ProbesOcclusion;
#else
half4 shadowMask = 1.0;
#endif
#if _ADDITIONAL_LIGHTS_VERTEX
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, positionWS, shadowMask);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
o.lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
}
#elif _ADDITIONAL_LIGHTS
o.shadowMask = shadowMask;
#endif
#else
#ifdef _ADDITIONAL_LIGHTS_VERTEX
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, positionWS);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
o.lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
}
#endif
#endif
return o;
}
half4 frag(Varyings i) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(i);
//光照
half3 lightColor = i.lightColor;
#ifdef _RECEIVESHADOWS_ON
Light main_light = GetMainLight(i.shadowCoord);
half3 main_attenuatedLightColor = main_light.color * main_light.distanceAttenuation * main_light.shadowAttenuation;
lightColor += LightingLambert(main_attenuatedLightColor, main_light.direction, i.normalWS);
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz, i.shadowMask);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
}
#endif
#else
Light main_light = GetMainLight();
half3 main_attenuatedLightColor = main_light.color * main_light.distanceAttenuation * main_light.shadowAttenuation;
lightColor += LightingLambert(main_attenuatedLightColor, main_light.direction, i.normalWS);
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz);
half3 attenuatedLightColor = light.color * light.distanceAttenuation * light.shadowAttenuation;
lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
}
#endif
#endif
//环境光
half3 ambient = half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
half4 col = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
col.rgb *= _BaseColor.rgb * lightColor + ambient;
#ifdef _ALPHATEST_ON
col.a = AlphaDiscard(col.a, _Cutoff);
#else
col.a = 1.0;
#endif
return col;
}
ENDHLSL
}
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
// -------------------------------------
// Render State Commands
ZWrite On
ZTest LEqual
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Universal Pipeline keywords
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
ENDHLSL
}
Pass
{
// Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with
// no LightMode tag are also rendered by Universal Render Pipeline
Name "GBuffer"
Tags { "LightMode" = "UniversalGBuffer" }
// -------------------------------------
// Render State Commands
ZWrite[_ZWrite]
ZTest LEqual
Cull[_Cull]
HLSLPROGRAM
#pragma target 4.5
// Deferred Rendering Path does not support the OpenGL-based graphics API:
// Desktop OpenGL, OpenGL ES 3.0, WebGL 2.0.
#pragma exclude_renderers gles3 glcore
// -------------------------------------
// Shader Stages
#pragma vertex LitGBufferPassVertex
#pragma fragment LitGBufferPassFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local_fragment _ALPHATEST_ON
//#pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON
#pragma shader_feature_local_fragment _EMISSION
#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature_local_fragment _OCCLUSIONMAP
#pragma shader_feature_local _PARALLAXMAP
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
#pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF
#pragma shader_feature_local_fragment _SPECULAR_SETUP
#pragma shader_feature_local _RECEIVE_SHADOWS_OFF
// -------------------------------------
// Universal Pipeline keywords
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
//#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
#pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
#pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
#pragma multi_compile_fragment _ _RENDER_PASS_ENABLED
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"
// -------------------------------------
// Unity defined keywords
#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
#pragma multi_compile _ SHADOWS_SHADOWMASK
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DYNAMICLIGHTMAP_ON
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma instancing_options renderinglayer
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitGBufferPass.hlsl"
ENDHLSL
}
Pass
{
Name "DepthOnly"
Tags { "LightMode" = "DepthOnly" }
// -------------------------------------
// Render State Commands
ZWrite On
ColorMask R
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
ENDHLSL
}
// This pass is used when drawing to a _CameraNormalsTexture texture
Pass
{
Name "DepthNormals"
Tags { "LightMode" = "DepthNormals" }
// -------------------------------------
// Render State Commands
ZWrite On
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex DepthNormalsVertex
#pragma fragment DepthNormalsFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local _PARALLAXMAP
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
// -------------------------------------
// Universal Pipeline keywords
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlsl"
ENDHLSL
}
// This pass it not used during regular rendering, only for lightmap baking.
Pass
{
Name "Meta"
Tags { "LightMode" = "Meta" }
// -------------------------------------
// Render State Commands
Cull Off
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex UniversalVertexMeta
#pragma fragment UniversalFragmentMetaLit
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _SPECULAR_SETUP
#pragma shader_feature_local_fragment _EMISSION
#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
#pragma shader_feature_local_fragment _SPECGLOSSMAP
#pragma shader_feature EDITOR_VISUALIZATION
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitMetaPass.hlsl"
ENDHLSL
}
Pass
{
Name "Universal2D"
Tags { "LightMode" = "Universal2D" }
// -------------------------------------
// Render State Commands
Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex vert
#pragma fragment frag
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/Utils/Universal2D.hlsl"
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
六、效果图
七、结语
有了以上的模板Shader,这样就可以在第一个Pass里随意自定义自己想要的效果,例如给Shader加一个外描边功能,给Shader加一个溶解功能等等