Search Unity

GPU Instances with shadows. How? Possible?

Discussion in 'Shaders' started by DrDumle, Jul 4, 2018.

  1. DrDumle

    DrDumle

    Joined:
    May 3, 2018
    Posts:
    14
    I'm trying to do a shader with instancing. But the shadows go through all the instanced objects. :(
    Like this


    I'm using the example code found here in the docs, still it doesn't work.

    Code (CSharp):
    1.           Shader "Instanced/InstancedShader" {
    2.     Properties {
    3.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    4.     }
    5.     SubShader {
    6.  
    7.         Pass {
    8.  
    9.             Tags {"LightMode"="ForwardBase"}
    10.  
    11.             CGPROGRAM
    12.  
    13.             #pragma vertex vert
    14.             #pragma fragment frag
    15.             #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
    16.             #pragma target 4.5
    17.  
    18.             #include "UnityCG.cginc"
    19.             #include "UnityLightingCommon.cginc"
    20.             #include "AutoLight.cginc"
    21.  
    22.             sampler2D _MainTex;
    23.  
    24.         #if SHADER_TARGET >= 45
    25.             StructuredBuffer<float4> positionBuffer;
    26.         #endif
    27.  
    28.             struct v2f
    29.             {
    30.                 float4 pos : SV_POSITION;
    31.                 float2 uv_MainTex : TEXCOORD0;
    32.                 float3 ambient : TEXCOORD1;
    33.                 float3 diffuse : TEXCOORD2;
    34.                 float3 color : TEXCOORD3;
    35.                 SHADOW_COORDS(4)
    36.             };
    37.  
    38.             void rotate2D(inout float2 v, float r)
    39.             {
    40.                 float s, c;
    41.                 sincos(r, s, c);
    42.                 v = float2(v.x * c - v.y * s, v.x * s + v.y * c);
    43.             }
    44.  
    45.             v2f vert (appdata_full v, uint instanceID : SV_InstanceID)
    46.             {
    47.             #if SHADER_TARGET >= 45
    48.                 float4 data = positionBuffer[instanceID];
    49.             #else
    50.                 float4 data = 0;
    51.             #endif
    52.  
    53.                 float rotation = data.w * data.w * _Time.x * 0.5f;
    54.                 rotate2D(data.xz, rotation);
    55.  
    56.                 float3 localPosition = v.vertex.xyz * data.w;
    57.                 float3 worldPosition = data.xyz + localPosition;
    58.                 float3 worldNormal = v.normal;
    59.  
    60.  
    61.  
    62.                 float3 ndotl = saturate(dot(worldNormal, _WorldSpaceLightPos0.xyz));
    63.                 float3 ambient = ShadeSH9(float4(worldNormal, 1.0f));
    64.                 float3 diffuse = (ndotl * _LightColor0.rgb);
    65.                 float3 color = v.color;
    66.  
    67.                 v2f o;
    68.                 o.pos = mul(UNITY_MATRIX_VP, float4(worldPosition, 1.0f));
    69.                 o.uv_MainTex = v.texcoord;
    70.                 o.ambient = ambient;
    71.                 o.diffuse = diffuse;
    72.                 o.color = color;
    73.                 TRANSFER_SHADOW(o)
    74.                 return o;
    75.             }
    76.  
    77.             fixed4 frag (v2f i) : SV_Target
    78.             {
    79.                 fixed shadow = SHADOW_ATTENUATION(i);
    80.                 fixed4 albedo = tex2D(_MainTex, i.uv_MainTex);
    81.                 float3 lighting = i.diffuse * shadow + i.ambient;
    82.                 fixed4 output = fixed4(albedo.rgb * i.color * lighting, albedo.w);
    83.                 UNITY_APPLY_FOG(i.fogCoord, output);
    84.                 return output;
    85.             }
    86.  
    87.             ENDCG
    88.         }
    89.     }
    90. }
     
  2. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    328
    Try to add second pass with Tags{ "LightMode" = "ShadowCaster" } .
     
  3. DrDumle

    DrDumle

    Joined:
    May 3, 2018
    Posts:
    14
    I've tried it. Still not working.



    Code (CSharp):
    1. Shader "Instanced/testH" {
    2. Properties {
    3. _MainTex ("Base (RGB)", 2D) = "white" {}//Needed by the Diffuse Fallback
    4. }
    5.  
    6. CGINCLUDE  ///reusable stuff here, in all passes
    7.  
    8.              #pragma target 4.5
    9.          
    10.             StructuredBuffer<float4> positionBuffer;
    11.              
    12. ENDCG
    13.  
    14.  
    15.  
    16. SubShader {
    17. Tags { "RenderType"="Opaque" }
    18. //LOD 200
    19.  
    20.  
    21. Pass{
    22. Tags { "LightMode" = "ForwardBase" }
    23. CGPROGRAM
    24. #pragma vertex vert
    25. #pragma fragment frag
    26. #pragma multi_compile_fwdbase
    27. #include "UnityCG.cginc"
    28. #include "AutoLight.cginc"
    29.  
    30. struct vertOut {
    31. float4 pos : SV_POSITION;
    32. LIGHTING_COORDS(0,1) // NEEDED FOR SHADOWS.
    33. };
    34.  
    35. vertOut vert(appdata_base v, uint instanceID : SV_InstanceID)
    36. {
    37. vertOut o;
    38. o.pos= UnityObjectToClipPos(v.vertex + positionBuffer[instanceID]);
    39. TRANSFER_VERTEX_TO_FRAGMENT(o); // NEEDED FOR SHADOWS.
    40. return o;
    41. }
    42.  
    43. float4 frag(vertOut i):COLOR
    44. {
    45. fixed atten = LIGHT_ATTENUATION(i);// NEEDED FOR SHADOWS.
    46. float4 c;
    47. c = float4(0,1,0,1) * atten;
    48. return c;
    49. }
    50. ENDCG
    51. }//Pass
    52.  
    53.  
    54.  
    55. // Pass to render object as a shadow caster
    56. Pass {
    57. Name "ShadowCaster"
    58. Tags { "LightMode" = "ShadowCaster" }
    59.  
    60. Fog {Mode Off}
    61. ZWrite On ZTest LEqual Cull Off
    62. Offset 1, 1
    63.  
    64. CGPROGRAM
    65. #pragma vertex vert
    66. #pragma fragment frag
    67. #pragma multi_compile_shadowcaster
    68. #pragma fragmentoption ARB_precision_hint_fastest
    69. #include "UnityCG.cginc"
    70. #include "AutoLight.cginc"
    71.  
    72. struct v2f {
    73. V2F_SHADOW_CASTER;
    74. };
    75.  
    76. v2f vert(appdata_base v, uint instanceID : SV_InstanceID)
    77. {
    78. v2f o;
    79. o.pos += positionBuffer[instanceID];
    80. TRANSFER_SHADOW_CASTER(o)
    81. return o;
    82. }
    83.  
    84. float4 frag( v2f i ) : COLOR
    85. {
    86. SHADOW_CASTER_FRAGMENT(i)
    87. }
    88. ENDCG
    89. } //Pass
    90.  
    91. }
    92.  
    93. }


    If unity's team put an example shader in the docs, it should work.. but it aint...
     
    Last edited: Jul 5, 2018
  4. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    328
    Basic GPU instancing with shadow casting and receiving.

    Code (CSharp):
    1.  
    2. // https://github.com/przemyslawzaworski/Unity3D-CG-programming
    3. using UnityEngine;
    4.  
    5. public class instancing : MonoBehaviour
    6. {
    7.     public Mesh Quad;
    8.     public Material GrassMaterial;
    9.     public Texture2D GrassTexture;
    10.     public Vector3 VolumeCenter = new Vector3 (0.0f,0.0f,0.0f);
    11.     public Vector3 VolumeSize = new Vector3 (2000.0f,2000.0f,2000.0f);
    12.     public int R = 100;
    13.     [Range(0.0f,1.0f)]
    14.     public float CutOff = 0.5f;
    15.    
    16.     private ComputeBuffer GeometryBuffer;
    17.     private ComputeBuffer ArgumentsBuffer;
    18.     private Bounds bounds;
    19.    
    20.     void Start ()
    21.     {
    22.         GeometryBuffer = new ComputeBuffer(R*R, 16);  
    23.         Vector4[] geometry = new Vector4[R*R];
    24.         for (int i=0;i<R*R;i++) geometry[i] = new Vector4(i%R,0.0f,(i%(R*R))/R,0.0f);  
    25.         GeometryBuffer.SetData(geometry);
    26.         GrassMaterial.SetBuffer("GeometryBuffer", GeometryBuffer);
    27.         uint[] args = new uint[5];
    28.         ArgumentsBuffer = new ComputeBuffer(1, 20, ComputeBufferType.IndirectArguments);      
    29.         args[0] = (uint)Quad.GetIndexCount(0);
    30.         args[1] = (uint)(R*R);
    31.         args[2] = (uint)Quad.GetIndexStart(0);
    32.         args[3] = (uint)Quad.GetBaseVertex(0);
    33.         args[4] = (uint)0;
    34.         ArgumentsBuffer.SetData(args);
    35.         GrassMaterial.SetTexture ("GrassTexture", GrassTexture);
    36.         bounds = new Bounds(VolumeCenter,VolumeSize);
    37.     }
    38.    
    39.     void Update ()
    40.     {
    41.         GrassMaterial.SetFloat("CutOff",CutOff);
    42.         Graphics.DrawMeshInstancedIndirect(Quad, 0, GrassMaterial, bounds, ArgumentsBuffer,0, null);      
    43.     }
    44.    
    45.     void OnDisable()
    46.     {
    47.         GeometryBuffer.Release();
    48.         ArgumentsBuffer.Release();
    49.     }
    50. }
    Code (CSharp):
    1.  
    2. // https://github.com/przemyslawzaworski/Unity3D-CG-programming
    3. Shader "Instancing"
    4. {
    5.     CGINCLUDE
    6.     #pragma vertex vertex_shader
    7.     #pragma fragment pixel_shader
    8.     #pragma target 5.0
    9.     sampler2D GrassTexture;
    10.     StructuredBuffer<float4> GeometryBuffer;
    11.     float CutOff;
    12.     ENDCG
    13.    
    14.     SubShader
    15.     {
    16.         Tags { "IgnoreProjector"="True" "RenderType"="Grass" "DisableBatching"="True"}
    17.         Pass
    18.         {
    19.             Tags{ "LightMode" = "ForwardBase" }
    20.             Cull Off              
    21.             CGPROGRAM      
    22.             #pragma multi_compile_fwdbase
    23.             #include "AutoLight.cginc"
    24.  
    25.             struct APPDATA
    26.             {
    27.                 float4 vertex : POSITION;
    28.                 float2 uv : TEXCOORD0;
    29.                 uint instanceID : SV_InstanceID;
    30.             };
    31.            
    32.             struct SHADERDATA
    33.             {
    34.                 float4 vertex : SV_POSITION;
    35.                 float2 uv : TEXCOORD0;
    36.                 float4 _ShadowCoord : TEXCOORD1;
    37.             };
    38.            
    39.             float4 ComputeScreenPos (float4 p)
    40.             {
    41.                 float4 o = p * 0.5;
    42.                 return float4(o.x + o.w, o.y*_ProjectionParams.x + o.w, p.zw);    
    43.             }
    44.            
    45.             SHADERDATA vertex_shader (APPDATA data)
    46.             {
    47.                 SHADERDATA vs;
    48.                 float4 buffer = GeometryBuffer[data.instanceID];              
    49.                 vs.vertex = mul(UNITY_MATRIX_VP, buffer + data.vertex);
    50.                 vs.uv = data.uv;
    51.                 vs._ShadowCoord = ComputeScreenPos(vs.vertex);
    52.                 return vs;
    53.             }
    54.            
    55.             float4 pixel_shader (SHADERDATA ps) : SV_Target
    56.             {
    57.                 float attenuation = SHADOW_ATTENUATION(ps);
    58.                 float4 color = tex2D(GrassTexture, ps.uv);              
    59.                 clip (color.a-CutOff);
    60.                 return color * attenuation ;
    61.             }
    62.             ENDCG
    63.         }
    64.        
    65.         Pass
    66.         {
    67.             Tags{ "LightMode" = "ShadowCaster" }  
    68.             Cull Off                  
    69.             CGPROGRAM
    70.                                                        
    71.             void vertex_shader (inout float4 vertex:POSITION,inout float2 uv:TEXCOORD0,uint i:SV_InstanceID)
    72.             {              
    73.                 vertex = mul(UNITY_MATRIX_VP,GeometryBuffer[i]+vertex);
    74.             }
    75.            
    76.             float4 pixel_shader (float4 vertex:POSITION, float2 uv:TEXCOORD0) : SV_Target
    77.             {
    78.                 float4 color = tex2D(GrassTexture,uv);              
    79.                 clip (color.a-CutOff);
    80.                 return 0;
    81.             }
    82.             ENDCG
    83.         }              
    84.     }  
    85. }
     
  5. DrDumle

    DrDumle

    Joined:
    May 3, 2018
    Posts:
    14
    Cool thanks!
     
  6. andrewzimmer

    andrewzimmer

    Joined:
    Jun 6, 2015
    Posts:
    4
    Adding to this in case you are not using screenspace shadows (IE: UNITY_NO_SCREENSPACE_SHADOWS is defined).

    I found this:
    Code (CSharp):
    1. #define TRANSFER_SHADOW(a) a._ShadowCoord = mul( unity_WorldToShadow[0], mul( unity_ObjectToWorld, v.vertex ) );
    in the unity shader includes, which translates to

    Code (CSharp):
    1. float4 inWorld = mul(\*Your object 2 world transform*/, v.vertex);
    2. o._ShadowCoord = mul(unity_WorldToShadow[0], inWorld);
    in the vertex shader. The default fails to work because unity_ObjectToWorld is obviously wrong for instanced placements of objects.