Использование теней в пользовательском шейдере URP
Чтобы использовать тени в пользовательском шейдере Universal Render Pipeline (URP), выполните следующие действия:
- Добавьте
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"внутрьHLSLPROGRAMв вашем файле шейдера. ФайлCore.hlslимпортирует файлыShadows.hlslиRealtimeLights.hlsl. - Используйте любой из методов, описанных в следующих разделах.
Получить позицию в теневом пространстве
Используйте эти методы для преобразования позиций в позиции теневых карт.
| Метод | Синтаксис | Описание |
|---|---|---|
GetShadowCoord |
float4 GetShadowCoord(VertexPositionInputs vertexInputs) |
Преобразует положение вершины в пространство тени. См. Transform позиции в пользовательском URP шейдере для информации о ходе работы VertexPositionInputs struct. |
TransformWorldToShadowCoord |
float4 TransformWorldToShadowCoord(float3 positionInWorldSpace) |
Преобразует позицию в мировом пространстве в пространство тени. |
Вычисление теней
Следующие методы рассчитывают тени с помощью сопоставлений теней. Чтобы использовать эти методы, сначала выполните следующие действия:
- Убедитесь, что в вашей сцене есть объекты, которые имеют пропуск шейдера
ShadowCaster, например объекты, которые используют шейдерUniversal Render Pipeline/Lit. - Добавьте
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREENк вашему шейдеру, чтобы он мог получить доступ к карте теней для основного света. - Добавьте
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWSк вашему шейдеру, чтобы он мог получить доступ к картам теней для дополнительного освещения.
| Метод | Синтаксис | Описание |
|---|---|---|
GetMainLight |
Light GetMainLight(float4 shadowCoordinates) |
Возвращает главный свет в сцене, со значением shadowAttenuation, основанным на том, находится ли позиция в координатах тени в тени. |
ComputeCascadeIndex |
half ComputeCascadeIndex(float3 positionInWorldSpace) |
Возвращает индекс каскада теней на позиции в мировом пространстве. Подробнее см. в Каскады теней. |
MainLightRealtimeShadow |
half MainLightRealtimeShadow(float4 shadowCoordinates) |
Возвращает значение тени из главного отображения тени на координатах. Подробнее см. в Отображение тени. |
AdditionalLightRealtimeShadow |
half AdditionalLightRealtimeShadow(int lightIndex, float3 positionInWorldSpace) |
Возвращает значение тени из дополнительной карты светлых теней на позиции в мировом пространстве. |
GetMainLightShadowFade |
half GetMainLightShadowFade(float3 positionInWorldSpace) |
Возвращает величину, на которую тени от основного света должны исчезнуть, исходя из расстояния между позицией и камерой. |
GetAdditionalLightShadowFade |
half GetAdditionalLightShadowFade(float3 positionInWorldSpace) |
Возвращает величину, на которую должна затухать тень от дополнительных источников света, исходя из расстояния между позицией и камерой. |
ApplyShadowBias |
float3 ApplyShadowBias(float3 positionInWorldSpace, float3 normalWS, float3 lightDirection) |
Добавление тени к позиции в пространстве мира. Подробнее см. в Устранение неисправностей тени. |
Пример
Этот пример кода является упрощенным примером рисования теней на поверхности. Он может не работать правильно с более чем одним каскад тени.
Чтобы генерировать тени, убедитесь, что в вашей сцене есть объекты, которые имеют пропуск шейдера ShadowCaster, например объекты, которые используют шейдер Universal Render Pipeline/Lit.
Shader "Custom/SimpleShadows"
{
SubShader
{
Tags { "RenderType" = "AlphaTest" "RenderPipeline" = "UniversalPipeline" }
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#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;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float4 shadowCoords : TEXCOORD3;
};
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
// Get the VertexPositionInputs for the vertex position
VertexPositionInputs positions = GetVertexPositionInputs(IN.positionOS.xyz);
// Convert the vertex position to a position on the shadow map
float4 shadowCoordinates = GetShadowCoord(positions);
// Pass the shadow coordinates to the fragment shader
OUT.shadowCoords = shadowCoordinates;
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
// Get the value from the shadow map at the shadow coordinates
half shadowAmount = MainLightRealtimeShadow(IN.shadowCoords);
// Set the fragment color to the shadow value
return shadowAmount;
}
ENDHLSL
}
}
}