Search Unity

Question Sphere imposter shadow attenuation problem

Discussion in 'Shaders' started by ErgoAaronSum, Nov 24, 2021.

  1. ErgoAaronSum

    ErgoAaronSum

    Joined:
    Mar 6, 2017
    Posts:
    8
    Hi all,

    I am currently working on an imposter system for particles and I am starting out with a simple sphere, I have currently got a system up and running that takes a world normal and renders the lighting and samples the shadowCoord and produces the following.



    Imposter is on the left and real sphere is on the right.

    The problem however is that it only works when the imposter sphere is located at (0, 0, 0) and the illusion is broken when there is any translation. Below is the shader graph.



    The first thing I did was scale the world normal by 0.5 as I noticed the shadowCoord sampling was too small, next I tried to add the world position



    Now as you can see it allows for the translation to update the sampling. However, there is some sampling issues again. I guess my first question is why the 0.5 scaling is required for the world origin case and next, what kind of scaling is needed for the world position or am I going about this the wrong way? I have a feeling I may need to transform my world normal into object form and then add the position offset? I've tried a few combinations but can't seem to get it right.

    Here is the MainLight function:

    Code (CSharp):
    1. void MainLight_half(float3 WorldPos, out half3 Direction, out half3 Color, out half DistanceAtten, out half ShadowAtten)
    2. {
    3. #ifdef SHADERGRAPH_PREVIEW
    4.    Direction = half3(0.5, 0.5, 0);
    5.    Color = 1;
    6.    DistanceAtten = 1;
    7.    ShadowAtten = 1;
    8. #else
    9.     Light mainLight = GetMainLight();
    10.     Direction = mainLight.direction;
    11.     Color = mainLight.color;
    12.     DistanceAtten = mainLight.distanceAttenuation;
    13.  
    14.     float4 shadowCoord = TransformWorldToShadowCoord(WorldPos);
    15.  
    16.     ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
    17.     float shadowStrength = GetMainLightShadowStrength();
    18.     ShadowAtten = SampleShadowmap(shadowCoord, TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowSamplingData, shadowStrength, false);
    19. #endif
    20. }
    If it seems a big task I am willing to pay for time to consult me on it.

    Thank you for reading
     
    Last edited: Nov 24, 2021
  2. ErgoAaronSum

    ErgoAaronSum

    Joined:
    Mar 6, 2017
    Posts:
    8
    Update:
    Turns out to be something quite simple, I was using the Position (World) node rather than Object (Position) node.

    Here is the updated shader graph, I still have no idea why scaling the world normal by 0.5 seems to make it work:



    and a demo of the functionality:



    Now my final problem is that this solution only seems to work within a certain distance

     
  3. ErgoAaronSum

    ErgoAaronSum

    Joined:
    Mar 6, 2017
    Posts:
    8
    Update2:
    It was the shadow cascades that were the problem, the MainLight function needed to be updated.
    Code (CSharp):
    1. void MainLight_half(float3 WorldPos, out half3 Direction, out half3 Color, out half DistanceAtten, out half ShadowAtten)
    2. {
    3. #ifdef SHADERGRAPH_PREVIEW
    4.    Direction = half3(0.5, 0.5, 0);
    5.    Color = 1;
    6.    DistanceAtten = 1;
    7.    ShadowAtten = 1;
    8. #else
    9.     Light mainLight = GetMainLight();
    10.     Direction = mainLight.direction;
    11.     Color = mainLight.color;
    12.     DistanceAtten = mainLight.distanceAttenuation;
    13.  
    14.     half cascadeIndex = ComputeCascadeIndex(WorldPos);
    15.     float4 shadowCoord = mul(_MainLightWorldToShadow[cascadeIndex], float4(WorldPos, 1.0));
    16.  
    17.     ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
    18.     float shadowStrength = GetMainLightShadowStrength();
    19.     ShadowAtten = SampleShadowmap(shadowCoord, TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowSamplingData, shadowStrength, false);
    20. #endif
    21. }