Notice
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

자라고싶다

[UnityShader/HLSL] Simple Sub Surface Scattering 본문

Unity/UnityShader

[UnityShader/HLSL] Simple Sub Surface Scattering

멍산 2025. 4. 8. 06:09

Shader "Custom/SSS_Forward_MainLight"
{
    Properties
    {
        _BaseColor("BaseColor", Color) = (1,1,1,1)
        _Thickness("Subsurface Thickness", Range(0, 1)) = 0.5
        _ScatteringFactor("ScatteringFactor", Range(1,4)) = 2
        [HDR]_SSSColor("Subsurface Color", Color) = (1, 0.4, 0.3, 1)
    }

    SubShader
    {
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes
            {
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
            };

            struct Varyings
            {
                float4 positionHCS : SV_POSITION;
                float3 normalWS : TEXCOORD0;
                float3 positionWS : TEXCOORD1;
            };

            float _Thickness;
            half4 _SSSColor;
            half4 _BaseColor;

            float _ScatteringFactor;

            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz);
                OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS);
                OUT.positionHCS = TransformWorldToHClip(OUT.positionWS);
                return OUT;
            }

            float3 SubsurfaceLighting(float3 N, float3 L, float3 V, float thickness)
            {
                float3 H = normalize(L + V);
                float NdotL = saturate(dot(N, L));
                float forwardScatter = pow(saturate(dot(-L, V)), _ScatteringFactor); // Light passing through
                //float forwardScatter = pow(saturate(dot(-L, V)), _ScatteringFactor) * (1 / (4 * 3.1415)); //HeyneyGreenstein Phase Function
                return _SSSColor.rgb * forwardScatter * thickness * (1-NdotL);
            }

            float4 frag(Varyings IN) : SV_Target
            {
                float3 N = normalize(IN.normalWS);
                float3 V = normalize(_WorldSpaceCameraPos - IN.positionWS);
                float3 AL = SampleSH(N);

                Light mainLight = GetMainLight();
                float3 L = normalize(mainLight.direction);

                float NdotL = saturate(dot(N,L));

                float3 sss = SubsurfaceLighting(N, L, V, _Thickness);
                float4 color = _BaseColor;
                color.rgb *= mainLight.color;
                

                color.rgb *= NdotL;
                color.rgb += _BaseColor.rgb * AL;
                color.rgb +=  sss.rgb * mainLight.color;
                return float4(color.rgb, 1);
            }
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

 

 

forwardScatter  에 (1 / (4 * 3.1415)) 를 곱하면  HeyneyGreenstein Phase Function 에 좀 더 근접한 수식을 구현할 수 있다.

 

추가로 공부할 것

- Diffusion Profile

- Thickness Map 추가

- ScreenSpace 기반 SSS 구현

- Additional Light 추가?

'Unity > UnityShader' 카테고리의 다른 글

[HLSL]Henyey-Greenstein Phase Function  (0) 2025.03.25
[CustomEditor]프로퍼티 #1  (0) 2024.04.23
[HLSL]Tessellation + Displacement  (1) 2023.11.23
[HLSL] Diffuse Wrap + Shadow Ramp  (0) 2023.10.17
[HLSL]2 Pass Outline  (0) 2023.10.16