11-03-2022 04:52 AM - edited 11-03-2022 05:26 AM
I'm trying to get shadow cast against the passthrough image. I have a transparent shadow shader (attached to an invisible floor plane) that works fine against a UI Canvas/Image in 'Screen Space - Camera' (see screenshot). When I remove that UI image though, I was expecting it to render that shadow over the passthrough image on the headset, since the passthrough image is at the back. However, no shadow gets rendered.
Has anyone done this sucessfully?
11-07-2022 07:49 AM
Yes, I've got it to work with URP.
What I think was happening in our case is that the Passthrough Layer was rendered afterwards, and used the alpha value in the framebuffer for blending. So if your shadows are rendering and not setting the alpha to >0, they will be completely overwritten by the passthrough image.
So a good thing to try would be to modify whichever shader renders your shadows to output an alpha value (say 1.0 or 255 to start with).
11-07-2022 01:50 PM - edited 11-08-2022 01:21 AM
That's great to know someone has got it working. I suspected this might be the case. Would you be able to share your shader code here? Are you doing some kind of multi-pass? Thanks!
11-08-2022 10:46 AM
I can't post the whole shader, but I think the crucial bit is to make sure you output a value for the alpha in the fragment shader:
return half4(0, 0, 0, alphaWithShadowStrength);
And I have my RenderQueue set to (Geometry - 1), so 1999. ZWrite On, Cull Off.
11-08-2022 03:48 PM - edited 11-08-2022 04:47 PM
Actually, I think the shader I'm using may already be doing this...
color = lerp(half4(1,1,1,1), _ShadowColor, (1.0 - shadowAttenutation) * _ShadowColor.a);
Which would make sense since it works in the 'run' window. But it still doesn't work in the headset. May I ask what your 'Blend' is set to?
11-08-2022 05:29 PM - edited 11-08-2022 05:30 PM
I think I finally got it working. The original shader was...
Shader "URP AR Shadow Receiver"
{
Properties
{
_ShadowColor ("Shadow Color", Color) = (0.35,0.4,0.45,1.0)
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Transparent"
"Queue"="Transparent-1"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Blend DstColor Zero, Zero One
Cull Back
ZTest LEqual
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _ShadowColor;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 positionWS : TEXCOORD0;
float fogCoord : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.positionWS = vertexInput.positionWS;
output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
return output;
}
half4 frag (Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
half4 color = half4(1,1,1,1);
#ifdef _MAIN_LIGHT_SHADOWS
VertexPositionInputs vertexInput = (VertexPositionInputs)0;
vertexInput.positionWS = input.positionWS;
float4 shadowCoord = GetShadowCoord(vertexInput);
half shadowAttenutation = MainLightRealtimeShadow(shadowCoord);
color = lerp(half4(1,1,1,1), _ShadowColor, (1.0 - shadowAttenutation) * _ShadowColor.a);
color.rgb = MixFogColor(color.rgb, half3(1,1,1), input.fogCoord);
#endif
return color;
}
ENDHLSL
}
}
}
I had to change the Blend mode and color output from frag() to get it to work...
Shader "My Shadow Shader"
{
Properties
{
_ShadowColor ("Shadow Color", Color) = (0.35,0.4,0.45,1.0)
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Transparent"
"Queue"="Transparent-1"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Blend SrcAlpha OneMinusSrcAlpha
Cull Back
ZTest LEqual
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _ShadowColor;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 positionWS : TEXCOORD0;
float fogCoord : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.positionWS = vertexInput.positionWS;
output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
return output;
}
half4 frag (Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
half4 color = half4(1,1,1,1);
#ifdef _MAIN_LIGHT_SHADOWS
VertexPositionInputs vertexInput = (VertexPositionInputs)0;
vertexInput.positionWS = input.positionWS;
float4 shadowCoord = GetShadowCoord(vertexInput);
half shadowAttenutation = MainLightRealtimeShadow(shadowCoord);
color = lerp(half4(0,0,0,0), _ShadowColor, (1.0 - shadowAttenutation));
#endif
return color;
}
ENDHLSL
}
}
}
I'm sure it's still not perfect, but at least I'm getting some kind of reasonable shadow out. Next, to see if I can use the Oculus room geometry to cast the shadow onto walls, desks, etc. Appreciate your pointers very much, thank you!
11-08-2022 05:33 PM - edited 11-08-2022 05:46 PM
I finally got it to work. I had to change the Blend mode and the color output from frag() to get it to work. The original shader I pinched was...
Shader "URP AR Shadow Receiver"
{
Properties
{
_ShadowColor ("Shadow Color", Color) = (0.35,0.4,0.45,1.0)
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Transparent"
"Queue"="Transparent-1"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Blend DstColor Zero, Zero One
Cull Back
ZTest LEqual
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _ShadowColor;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 positionWS : TEXCOORD0;
float fogCoord : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.positionWS = vertexInput.positionWS;
output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
return output;
}
half4 frag (Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
half4 color = half4(1,1,1,1);
#ifdef _MAIN_LIGHT_SHADOWS
VertexPositionInputs vertexInput = (VertexPositionInputs)0;
vertexInput.positionWS = input.positionWS;
float4 shadowCoord = GetShadowCoord(vertexInput);
half shadowAttenutation = MainLightRealtimeShadow(shadowCoord);
color = lerp(half4(1,1,1,1), _ShadowColor, (1.0 - shadowAttenutation) * _ShadowColor.a);
color.rgb = MixFogColor(color.rgb, half3(1,1,1), input.fogCoord);
#endif
return color;
}
ENDHLSL
}
}
}
After modification it's now...
Shader "My Shadow Shader"
{
Properties
{
_ShadowColor ("Shadow Color", Color) = (0.35,0.4,0.45,1.0)
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Transparent"
"Queue"="Transparent-1"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Blend SrcAlpha OneMinusSrcAlpha
Cull Back
ZTest LEqual
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _ShadowColor;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 positionWS : TEXCOORD0;
float fogCoord : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.positionWS = vertexInput.positionWS;
output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
return output;
}
half4 frag (Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
half4 color = half4(1,1,1,1);
#ifdef _MAIN_LIGHT_SHADOWS
VertexPositionInputs vertexInput = (VertexPositionInputs)0;
vertexInput.positionWS = input.positionWS;
float4 shadowCoord = GetShadowCoord(vertexInput);
half shadowAttenutation = MainLightRealtimeShadow(shadowCoord);
color = lerp(half4(0,0,0,0), _ShadowColor, (1.0 - shadowAttenutation));
#endif
return color;
}
ENDHLSL
}
}
}
I'm sure due to my lack of experience this is a bit off, but it seems to produce the desired effect. Next, I will try and project it onto the defined room geometry (walls, floor, desk etc.) that I can hopefully pick up from the SDK. Really appreciated your pointers here, thank you.
11-09-2022 01:25 AM
I got this working and I keep replying with my shader code, but my reply keeps getting wiped out. I don't know why. Anyway, thank you for the pointers, it helped a lot. I had to modify the 'Blend' to get it to work.
11-09-2022 03:51 AM
Great stuff! Glad you got it working.
02-15-2023 12:50 AM
Hi Raeldor,
thanks for your shader! I have the same problem but I cannot make it work! I checked everything pipeline related and any other settings. I used your shader and it shows shadows in the editor but not in the build on my quest 2. Did you also changed settings at the SelectivePassthrough-Material like ZTest or blend alpha?
Thanks for help, Can