Shader "Unlit/RenderPrimitivesShader"
{
    Properties
    {
        _BaseColor("Base Color", Color) = (0.1098039, 0.8784314, 0.870816, 1)
    }
    
    SubShader
    {
        Pass
        {
            ZWrite On
            ZTest LEqual
            Name "ForwardOnly"
            Tags { "LightMode" = "ForwardOnly" }
            
            HLSLPROGRAM

            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag
            #define ATTRIBUTES_NEED_NORMAL
            #define ATTRIBUTES_NEED_TANGENT
            #define VARYINGS_NEED_TANGENT_TO_WORLD
            
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON
            
            #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassRenderers.hlsl"
            
            StructuredBuffer<int> _Triangles;
            StructuredBuffer<float3> _Positions;
            uniform uint _StartIndex;
            uniform uint _BaseVertexIndex;
            uniform float _NumInstances;
            float3 _BaseColor;

            struct VertexToGeometry2
            {
                float4 position : POSITION;
                float3 positionOS : TEXCOORD0;
            };

            struct GeometryToFragment2
            {
                float4 position : POSITION;
                float3 normal : NORMAL;
            };

            //check it also:  https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Graphics.RenderPrimitives.html
            VertexToGeometry2 vert(AttributesMesh v, uint vertexID: SV_VertexID, uint svInstanceID : SV_InstanceID)
            {
                VertexToGeometry2 vtg;
                float3 pos = _Positions[_Triangles[vertexID + _StartIndex] + _BaseVertexIndex];
                v.positionOS = (/*v.positionOS +*/ pos + 1e-3 - float3(_NumInstances, 0, 0) + float4(1 + svInstanceID * 2, 1, 0, 0));
                vtg.position = TransformObjectToHClip(v.positionOS);
                vtg.positionOS = TransformObjectToWorld(v.positionOS);
                return vtg;
            }

            [maxvertexcount(3)]
            void geom(triangle VertexToGeometry2 i[3], inout TriangleStream<GeometryToFragment2> Stream)
            {                
                float3 Normal = normalize((cross(i[1].positionOS.xyz - i[0].positionOS.xyz, i[2].positionOS.xyz - i[0].positionOS.xyz)));
                [unroll]
                for (int j = 0; j < 3; j++)
                {
                    GeometryToFragment2 Output;

                    Output.position = i[j].position;
                    Output.normal = Normal;

                    Stream.Append(Output);
                }

                //Stream.RestartStrip();
            }
            
            float4 frag(GeometryToFragment2 input) : SV_Target
            {
                DirectionalLightData DirectionalLightData = _DirectionalLightDatas[0];

                float3 finalColor = SRGBToLinear(_BaseColor);
                finalColor *= DirectionalLightData.color;
                finalColor *= GetCurrentExposureMultiplier();
                finalColor *= saturate(dot(input.normal, -DirectionalLightData.forward));
                finalColor /= PI;
                
                return float4(finalColor, 1.0f);
            }
            ENDHLSL
        }
        
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }

            ZWrite On
            ZTest LEqual

            HLSLPROGRAM

            #pragma vertex vertShadowCaster
            #pragma fragment fragShadowCaster
            
            #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassRenderers.hlsl"
            #define UNITY_INDIRECT_DRAW_ARGS IndirectDrawIndexedArgs
            #include "UnityIndirect.cginc"
            
            StructuredBuffer<int> _Triangles;
            StructuredBuffer<float3> _Positions;
            uniform uint _StartIndex;
            uniform uint _BaseVertexIndex;
            uniform float _NumInstances;

            struct v2f
            {
                float4 pos : SV_POSITION;
            };
            v2f vertShadowCaster(AttributesMesh v, uint vertexID: SV_VertexID, uint svInstanceID : SV_InstanceID)
            {                
                InitIndirectDrawArgs(0);
                v2f o;
                uint instanceID = GetIndirectInstanceID(svInstanceID);
                float3 pos = _Positions[_Triangles[vertexID + _StartIndex] + _BaseVertexIndex];
                o.pos = TransformObjectToHClip(v.positionOS + pos + 1e-3 - float3(_NumInstances, 0, 0) + float3(1 + 2 * instanceID, 1, 0));
                return o;
            }

            float4 fragShadowCaster(v2f i) : SV_Target
            {       
                return 0;
            }
           
            ENDHLSL
        }

        Pass
        {
            Name "DepthOnly"
            Tags { "LightMode" = "DepthOnly" }

            ZWrite On
            ZTest LEqual

            HLSLPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            
            #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassRenderers.hlsl"
            #define UNITY_INDIRECT_DRAW_ARGS IndirectDrawIndexedArgs
            #include "UnityIndirect.cginc"
            
            StructuredBuffer<int> _Triangles;
            StructuredBuffer<float3> _Positions;
            uniform uint _StartIndex;
            uniform uint _BaseVertexIndex;
            uniform float _NumInstances;

            struct v2f
            {
                float4 pos : SV_POSITION;
            };
            v2f vert(AttributesMesh v, uint vertexID: SV_VertexID, uint svInstanceID : SV_InstanceID)
            {                
                InitIndirectDrawArgs(0);
                v2f o;
                uint instanceID = GetIndirectInstanceID(svInstanceID);
                float3 pos = _Positions[_Triangles[vertexID + _StartIndex] + _BaseVertexIndex];
                o.pos = TransformObjectToHClip(v.positionOS + pos + 1e-3 - float3(_NumInstances, 0, 0) + float3(1 + 2 * instanceID, 1, 0));
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {       
                return 0;
            }
           
            ENDHLSL
        }
        
        Pass
        {   
            Name "HTrace Voxelization"
            Tags { "LightMode" = "HTraceVoxelization" }
            
            Cull Off
            ZClip Off
            ZWrite Off
            Conservative False

            HLSLPROGRAM

            #pragma require geometry
            #pragma require randomwrite

            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON
            #pragma multi_compile CONSTANT_VOXELIZATION PARTIAL_VOXELIZATION DYNAMIC_VOXELIZATION
            
            #include "../../../../HTraceWSGI/Resources/HTraceWSGI/Includes/VoxelizationStages.hlsl"

            #pragma vertex VertCustom
            #pragma geometry VoxelizationGeom
            #pragma fragment VoxelizationFrag
            
            StructuredBuffer<int> _Triangles;
            StructuredBuffer<float3> _Positions;
            uniform uint _StartIndex;
            uniform uint _BaseVertexIndex;
            uniform float _NumInstances;

            // --- Vertex Stage ---
            VertexToGeometry VertCustom(AttributesMesh inputMesh, uint vertexID: SV_VertexID, uint svInstanceID : SV_InstanceID)
            {
                VertexToGeometry Output = VoxelizationVert(inputMesh);

                float3 pos = _Positions[_Triangles[vertexID + _StartIndex] + _BaseVertexIndex];
                float4 wpos = mul(GetObjectToWorldMatrix(), float4(pos - float3(_NumInstances,0,0) + float3(1 + 2 * svInstanceID, 1.0f, 0), 1.0f));
                Output.PositionCS = mul(UNITY_MATRIX_VP, wpos);
                
                #ifdef UNITY_REVERSED_Z
                Output.PositionCS.z = mad(Output.PositionCS.z, -2.0, 1.0);
                #endif
                
                return Output;
            }

            ENDHLSL
        }
    }
}

