Использовать освещение в пользовательском шейдере URP
Чтобы использовать освещение в пользовательском шейдере Universal Render Pipeline (URP), выполните следующие действия:
- Добавьте
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"внутрьHLSLPROGRAMв вашем файле шейдера. - Используйте любой из методов, описанных в следующих разделах.
Получить данные о свете
Файл Lighting.hlsl импортирует файл RealtimeLights.hlsl, который содержит следующие методы.
| Метод | Синтаксис | Описание |
|---|---|---|
GetMainLight |
Light GetMainLight() |
Возвращает основной свет в сцене. |
GetAdditionalLight |
Light GetAdditionalLight(uint lightIndex, float3 positionInWorldSpace) |
Возвращает дополнительный свет lightIndex, который влияет на positionWS. Например, если lightIndex является 0, этот метод возвращает первый дополнительный свет. |
GetAdditionalLightsCount |
int GetAdditionalLightsCount() |
Возвращает число дополнительных огней. Примечание: эта функция всегда возвращает 0 в пути отображения Forward+. Дополнительную информацию см. в Итерация над дополнительными огнями в пути отображения Forward+. |
См. Использование теней в пользовательском шейдере URP для информации о версиях этих методов, которые можно использовать для вычисления теней.
Рассчитать освещенность для поверхностной нормы
| Метод | Синтаксис | Описание |
|---|---|---|
LightingLambert |
half3 LightingLambert(half3 lightColor, half3 lightDirection, half3 surfaceNormal) |
Возвращает диффузное освещение для нормали поверхности, рассчитанное с использованием модели Ламберта. |
LightingSpecular |
half3 LightingSpecular(half3 lightColor, half3 lightDirection, half3 surfaceNormal, half3 viewDirection, half4 specularAmount, half smoothnessAmount) |
Возвращает зеркальное освещение для нормальной поверхности, используя простое затенение. |
Рассчитать окклюзию окружающей среды
Файл Lighting.hlsl импортирует файл AmbientOcclusion.hlsl, который содержит следующие методы.
| Метод | Синтаксис | Описание |
|---|---|---|
SampleAmbientOcclusion |
half SampleAmbientOcclusion(float2 normalizedScreenSpaceUV) |
Возвращает значение окклюзии окружающего пространства на позиции в пространстве экрана, где 0 означает окклюзию, а 1 — неокклюзию. |
GetScreenSpaceAmbientOcclusion |
AmbientOcclusionFactor GetScreenSpaceAmbientOcclusion(float2 normalizedScreenSpaceUV) |
Возвращает косвенные и прямые значения окклюзии окружающего пространства на позиции в пространстве экрана, где 0 означает окклюзию, а 1 — неокклюзию. |
См. Окклюзия окружающего света для получения дополнительной информации.
Структуры
AmbientOcclusionFactor
Используйте GetScreenSpaceAmbientOcclusion метод, чтобы вернуть эту структуру.
| Полевая | Описание |
|---|---|
half indirectAmbientOcclusion |
Степень, в которой объект находится в тени от окружающей окклюзии, вызванной объектами, блокирующими косвенный свет. |
half directAmbientOcclusion |
Степень, в которой объект находится в тени от окружающей окклюзии, вызванной объектами, блокирующими прямой свет. |
Свет
Используйте GetMainLight и GetAdditionalLight методы, чтобы вернуть эту структуру.
| Полевая | Описание |
|---|---|
half3 direction |
Направление света. |
half3 color |
Цвет света. |
float distanceAttenuation |
Сила света, основанная на его расстоянии от объекта. |
half shadowAttenuation |
Сила света, основанная на том, находится ли объект в тени. |
uint layerMask |
Маска слоя света. |
Пример
Следующий шейдер URP рисует поверхности объектов с количеством света, которое они получают от основного направленного света.
Shader "Custom/LambertLighting"
{
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv: TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv: TEXCOORD0;
half3 lightAmount : TEXCOORD2;
};
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
// Get the VertexNormalInputs of the vertex, which contains the normal in world space
VertexNormalInputs positions = GetVertexNormalInputs(IN.positionOS);
// Get the properties of the main light
Light light = GetMainLight();
// Calculate the amount of light the vertex receives
OUT.lightAmount = LightingLambert(light.color, light.direction, positions.normalWS.xyz);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
// Set the fragment color to the interpolated amount of light
return float4(IN.lightAmount, 1);
}
ENDHLSL
}
}
}