如何在阴影贴图中使用二维纹理数组
关于阴影贴图的 文档 指示我需要包含
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
关于2D数组的 [文档] 使用 UNITY\_DECLARE\_TEX2DARRAY,需要 #include "UnityCG.cginc"。但当我把它们同时包含时,它们似乎会冲突,导致编译错误:
redefinition of 'PackHeightmap' at
无论我使用CGPROGRAM还是HSLSLPROGRAM,问题都一样。
我尝试使用基于 #include "Lighting.cginc" 的较旧API,但到目前为止在任何地方都看不到阴影(但使用默认的Lit材质时会看到阴影)
Shader "Proc Env/Terrain"
{
Properties
{
_TerrainLayers ("Layers", 2DArray) = "" {}
_LayerWeights("Weight Map", 2D) = "white" {}
_UVScale ("UVScale", Float) = 1.0
}
SubShader
{
Tags { "RenderType" = "Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// texture arrays are not available everywhere,
// only compile shader on platforms where they are
#pragma require 2darray
// compile shader into multiple variants, with and without shadows
// (we don't care about any lightmaps yet, so skip these variants)
#pragma multi_compile_fwdbase // nolightmap nodirlightmap nodynlightmap novertexlight
//#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
//#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#include "UnityCG.cginc"
#include "Lighting.cginc"
// shadow helper functions and macros like SHADOW_COORDS, TRANSFER_SHADOW
#include "AutoLight.cginc"
struct Attributes
{
float4 positionOS : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWorld : TEXCOORD1;
SHADOW_COORDS(3) // put shadows data into TEXCOORD3
//float4 shadowCoords : TEXCOORD3;
float3 normal: NORMAL;
};
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionHCS = UnityObjectToClipPos(IN.positionOS);
//OUT.positionHCS = TransformObjectToHClip(IN.positionOS);
OUT.uv = IN.uv;
OUT.positionWorld = IN.positionOS;
OUT.normal = IN.normal;
//VertexPositionInputs positions = GetVertexPositionInputs(IN.positionOS.xyz);
//float4 shadowCoordinates = GetShadowCoord(positions);
// Pass the shadow coordinates to the fragment shader
//OUT.shadowCoords = shadowCoordinates;
TRANSFER_SHADOW(OUT);
return OUT;
}
UNITY_DECLARE_TEX2DARRAY(_TerrainLayers);
half4 frag (Varyings IN) : SV_Target
{
// compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed)
half shadowAmount = SHADOW_ATTENUATION(IN);
//half shadowAmount = MainLightRealtimeShadow(IN.shadowCoords);
return UNITY_SAMPLE_TEX2DARRAY(_TerrainLayers, float3(IN.positionWorld.x, IN.positionWorld.z, 2)) * shadowAmount;
}
ENDCG
}
// shadow casting support
UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
}
}
当我添加
Tags {"LightMode" = "LightweightForward"}
时,整个材质变成洋红色。我在Unity 6.4的 URP中使用。
我差点就把它调通了
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Proc Env/Terrain"
{
Properties
{
_TerrainLayers ("Layers", 2DArray) = "" {}
_LayerWeights("Weight Map", 2D) = "white" {}
_UVScale ("UVScale", Float) = 1.0
}
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma require 2darray
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWorld : TEXCOORD1;
float4 shadowCoords : TEXCOORD3;
float3 normal: NORMAL;
};
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionHCS = TransformObjectToHClip(IN.positionOS);
OUT.uv = IN.uv;
OUT.positionWorld = IN.positionOS;
OUT.normal = IN.normal;
VertexPositionInputs positions = GetVertexPositionInputs(IN.positionOS.xyz);
float4 shadowCoordinates = GetShadowCoord(positions);
OUT.shadowCoords = shadowCoordinates;\
return OUT;
}
TEXTURE2D_ARRAY(_TerrainLayers);
SAMPLER(sampler_TerrainLayers);
half4 frag (Varyings IN) : SV_Target
{
half shadowAmount = MainLightRealtimeShadow(IN.shadowCoords);
return SAMPLE_TEXTURE2D_ARRAY(_TerrainLayers, sampler_TerrainLayers, IN.positionWorld.xz, 2) * shadowAmount;
}
ENDHLSL
}
}
}
但它仍然产生了一些怪异的伪影。我觉得我完全按照官方示例来做。
我稍微查了一下,似乎是URP的一个bug
https://esotericsoftware.com/forum/d/15003-urp-shader-bug-when-on-edge-of-shadow-cascades/2
解决方案
原来这个问题的原因是在顶点着色器中计算shadowCoord,但如果在片段着色器中进行计算,一切都能正常工作。以下是完整代码
Shader "Proc Env/Terrain"
{
Properties
{
_TerrainLayers ("Layers", 2DArray) = "" {}
_LayerWeights("Weight Map", 2D) = "white" {}
_UVScale ("UVScale", Float) = 1.0
}
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma require 2darray
// this will allow for shadow cascades
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
// this will make the shadows soft
#pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWorld : TEXCOORD1;
float3 normal: NORMAL;
};
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionHCS = TransformObjectToHClip(IN.positionOS);
OUT.uv = IN.uv;
OUT.positionWorld = IN.positionOS;
OUT.normal = IN.normal;
return OUT;
}
TEXTURE2D_ARRAY(_TerrainLayers);
SAMPLER(sampler_TerrainLayers);
half4 frag (Varyings IN) : SV_Target
{
VertexPositionInputs positions = GetVertexPositionInputs(IN.positionWorld);
// compute shadow coords in fragment to avoid artifacts!
float4 shadowCoords = GetShadowCoord(positions);
half shadowAmount = MainLightRealtimeShadow(shadowCoords);
return SAMPLE_TEXTURE2D_ARRAY(_TerrainLayers, sampler_TerrainLayers, IN.positionWorld.xz, 2) * shadowAmount;
}
ENDHLSL
}
}
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。
