Shader "Course/Lesson15/TriplanarHLSL"
{
    Properties
    {
        _BaseMap ("Texture", 2D) = "white" {}
        _Tint ("Tint", Color) = (1, 1, 1, 1)
        _Tile ("Tile", Float) = 1
        _Blend ("Blend", Range(1, 8)) = 1
        [ToggleUI] _WorldSpace ("World Space", Float) = 0
        _Ambient ("Constant Fill", Range(0, 1)) = 0.2
    }
    SubShader
    {
        Tags { "RenderPipeline" = "UniversalPipeline" "RenderType" = "Opaque" }
        Pass
        {
            Tags { "LightMode" = "SRPDefaultUnlit" }
            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
            {
                float3 positionOS : POSITION;
                float3 normalOS : NORMAL;
            };
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float3 positionWS : TEXCOORD0;
                float3 normalWS : TEXCOORD1;
            };
            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);
            CBUFFER_START(UnityPerMaterial)
                float4 _Tint;
                float _Tile;
                float _Blend;
                float _WorldSpace;
                float _Ambient;
            CBUFFER_END

            Varyings Vert(Attributes input)
            {
                Varyings output;
                output.positionCS = TransformObjectToHClip(input.positionOS);
                output.positionWS = TransformObjectToWorld(input.positionOS);
                output.normalWS = TransformObjectToWorldNormal(input.normalOS);
                return output;
            }

            float4 Frag(Varyings input) : SV_Target
            {
                // Position and normal must use the same projection space.
                float3 normalWS = normalize(input.normalWS);
                float3 position = TransformWorldToObject(input.positionWS);
                float3 normal = TransformWorldToObjectNormal(normalWS);
                if (_WorldSpace > 0.5)
                {
                    position = GetAbsolutePositionWS(input.positionWS);
                    normal = normalWS;
                }

                float3 uv = position * _Tile;
                float3 weight = pow(abs(normal), _Blend);
                weight /= weight.x + weight.y + weight.z;

                float4 colorX = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv.zy);
                float4 colorY = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv.xz);
                float4 colorZ = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv.xy);
                float3 color = colorX.rgb * weight.x
                             + colorY.rgb * weight.y
                             + colorZ.rgb * weight.z;

                // Minimal Lambert lighting from lesson 14.
                Light mainLight = GetMainLight();
                float diffuse = saturate(dot(normalWS, mainLight.direction));
                return float4(color * _Tint.rgb * (diffuse + _Ambient), 1.0);
            }
            ENDHLSL
        }
    }
}
