user 010beaea75 Chore: NiloToonURP 업데이트 및 배경 썸네일 갱신
- NiloToonURP 외부 에셋 업데이트
- 배경 씬 썸네일 16:9 해상도로 갱신
- 렌더 파이프라인 설정 업데이트
- 외부 셰이더 그래프 업데이트 (LEDScreen, PIDI Planar Reflections)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 01:28:02 +09:00

189 lines
6.4 KiB
Plaintext

// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA)
// Copyright (c) 2021 Kuroneko ShaderLab Limited
// For more information, visit -> https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample
Shader "Hidden/NiloToon/AnimePostProcess"
{
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
sampler2D _NiloToonAverageShadowMapRT;
float _TopLightRotationDegree;
float _BottomDarkenRotationDegree;
float _TopLightDrawAreaHeight;
float _BottomDarkenDrawAreaHeight;
half _TopLightIntensity;
half _TopLightMultiplyLightColor;
half _TopLightDesaturate;
half3 _TopLightTintColor;
half3 _TopLightSunTintColor;
half _TopLightReceiveMainLightShadow;
half _BottomDarkenIntensity;
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
half3 color : TEXCOORD0;
};
// https://docs.unity3d.com/Packages/com.unity.shadergraph@12.0/manual/Rotate-Node.html
void Unity_Rotate_Degrees_float(float2 UV, float2 Center, float Rotation, out float2 Out)
{
Rotation = Rotation * (3.1415926f/180.0f);
UV -= Center;
float s = sin(Rotation);
float c = cos(Rotation);
float2x2 rMatrix = float2x2(c, -s, s, c);
rMatrix *= 0.5;
rMatrix += 0.5;
rMatrix = rMatrix * 2 - 1;
UV.xy = mul(UV.xy, rMatrix);
UV += Center;
Out = UV;
}
// input.positionOS is (-1,-1) to (1,1) rect full screen mesh
Varyings ScreenVertFullscreenMesh(Attributes input)
{
// default (_TopLightDrawAreaHeight == 0.5) only render top half of the screen to save fill-rate
input.positionOS.y -= 1; // after this line, input.positionOS.y's top = 0, bottom = -2
input.positionOS.y *= _TopLightDrawAreaHeight;
input.positionOS.y += 1;
// extend x to make rotation possible
input.positionOS.x *= 10;
// extend y to make rotation possible
if(input.uv.y > 0.5)
{
input.positionOS.y += 1;
input.uv.y += 1;
}
// apply rotate (rotation center is (0,0))
Unity_Rotate_Degrees_float(input.positionOS.xy, float2(0.0,0.0), _TopLightRotationDegree, input.positionOS.xy);
Varyings output = (Varyings)0;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
// light color
Light mainLight = GetMainLight();
mainLight.color = lerp(1,mainLight.color, _TopLightMultiplyLightColor);
half3 lightColor = mainLight.color * _TopLightSunTintColor; // tint orange to make it default looks better
float lightLuminance = Luminance(mainLight.color);
lightColor = lerp(lightColor, lightLuminance, _TopLightDesaturate); // we should lerp(mainLight.color,lightLuminance,_TopLightDesaturate), but since lots of user are using the wrong method to set _TopLightDesaturate already, we can't change it
lightColor *= _TopLightTintColor;
lightColor *= 1 / (1 + lightLuminance) * 3;
////////////////////////////////////
//skylight screen
////////////////////////////////////
float skyLightGradient = min(2,(max(0,input.uv.y * 2 - 1)));//linear gradient from top to middle, minmax(0,2) due to "extend y to make roation possible" section added
// reserved the right most slot for camera (uv.x == 1)
half averageShadowSampleValue = lerp(1,tex2Dlod(_NiloToonAverageShadowMapRT, float4(1,0,0,0)).r,_TopLightReceiveMainLightShadow);
float skyLightIntensity = 1.5 * _TopLightIntensity * averageShadowSampleValue; // for intensity, control this
half3 col = skyLightGradient * lightColor * skyLightIntensity;
output.color = col;
return output;
}
half4 ScreenFrag(Varyings input) : SV_Target
{
return half4(input.color * input.color,1); // better fadeout curve than linear
}
Varyings MultiplyVertFullscreenMesh(Attributes input)
{
// default (_BottomDarkenDrawAreaHeight == 0.5) only render bottom half of the screen to save fill-rate
input.positionOS.y += 1;
input.positionOS.y *= _BottomDarkenDrawAreaHeight;
input.positionOS.y -= 1;
// extend x to make rotation possible
input.positionOS.x *= 10;
// extend y to make rotation possible
if(input.uv.y < 0.5)
{
input.positionOS.y -= 1;
input.uv.y -= 1;
}
// apply rotate
Unity_Rotate_Degrees_float(input.positionOS.xy, float2(0.0,0.0), _BottomDarkenRotationDegree, input.positionOS.xy);
Varyings output = (Varyings)0;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
Light mainLight = GetMainLight();
float3 lightColor = mainLight.color;
float lightLuminance = Luminance(mainLight.color);
////////////////////////////////////
//bottom darken
////////////////////////////////////
half bottomDarkenGradient = input.uv.y; //linear gradient from bottom to middle
half darkenTo = 0.9 / (1.0 + lightLuminance * 0.25);
half3 col = lerp(1 , bottomDarkenGradient, saturate(darkenTo * _BottomDarkenIntensity));
output.color = col;
return output;
}
half4 MultiplyFrag(Varyings input) : SV_Target
{
return half4(input.color,1);
}
ENDHLSL
SubShader
{
ZTest Off ZWrite Off Cull Off
// Pass 0
Pass
{
Name "RenderAnimePostProcessScreen"
Blend OneMinusDstColor One // screen
ColorMask RGB
HLSLPROGRAM
#pragma vertex ScreenVertFullscreenMesh
#pragma fragment ScreenFrag
ENDHLSL
}
// Pass 1
Pass
{
Name "RenderAnimePostProcessMultiply"
Blend DstColor Zero // multiply
ColorMask RGB
HLSLPROGRAM
#pragma vertex MultiplyVertFullscreenMesh
#pragma fragment MultiplyFrag
ENDHLSL
}
}
}