Hey, i found a transparent shader that recieves shadows and it seems to be working perfectly well but ONLY in the Editor…
In the editor the color of the object is correct, which is the skybox
In the game, the color of the object is the background color of the camera!
Theres something going on here but i dont know what…
Top is editor (desired result) Bottom is gameplay (undesired)
And here’s the code:
Shader "Custom/TransparentShadowCollector"
{
Properties
{
_Color("Main Color", Color) = (1,1,1,.5)
_ShadowIntensity("Shadow Intensity", Range(0, 1)) = 0.6
}
SubShader
{
Tags{ "Queue" = "Geometry" }
Pass
{
Tags{ "LightMode" = "ForwardBase" }
Cull Back
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
uniform fixed4 _Color;
uniform float _ShadowIntensity;
struct v2f
{
float4 pos : SV_POSITION;
LIGHTING_COORDS(0,1)
};
v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
fixed4 frag(v2f i) : COLOR
{
float attenuation = LIGHT_ATTENUATION(i);
return fixed4(0,0,0,(1 - attenuation)*_ShadowIntensity) * _Color;
}
ENDCG
}
}
Fallback "Diffuse"
}
What’s going on here? It feels so close yet out of reach
I have a feeling it has soemthing to do with the LIGHTING_COORDS function but i can’t find any documentation on that dang thing!
Can anyone please help me out here, i don’t understand why it’d be working on one and not the other.
Is it possible to pull the skybox in specifically into the shader and then map the transparency as what the skybox output would be? Would that even work for what i’m trying to do?
Btw if this doesnt make sense what im doing, i’m trying to fake lighting onto a photo realistic skybox and it seems to be working on the editor but not the gameplay, the outputs are weird…
The magic keyword is “Matte Shadow”…
1 Like
I found one that seems to be for exact purpose that i’m using it for.
But the same dang issue! I have no idea whats wrong…
Why does it work perfectly in the editor and just use the damn background clear color for the camera in the game view…
Here’s the shader i found for it, it does exactly the same thing that the other one did… Just with a bit more control on the tranparency of the shadow
Shader "FX/Matte Shadow" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
LOD 200
Blend Zero SrcColor
CGPROGRAM
#pragma surface surf ShadowOnly alphatest:_Cutoff
fixed4 _Color;
struct Input {
float2 uv_MainTex;
} ;
inline fixed4 LightingShadowOnly (SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed4 c;
c.rgb = s.Albedo*atten;
c.a = s.Alpha;
return c;
}
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = _Color;
o.Albedo = c.rgb;
o.Alpha = 1;
}
ENDCG
}
Fallback "Transparent/Cutout/VertexLit"
}
I also found this one that also does the exact same thing
Shader "Custom/ShadowDrawer"
{
Properties
{
_Color ("Shadow Color", Color) = (0, 0, 0, 0.6)
}
CGINCLUDE
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f_shadow {
float4 pos : SV_POSITION;
LIGHTING_COORDS(0, 1)
};
half4 _Color;
v2f_shadow vert_shadow(appdata_full v)
This file has been truncated. show original
I tried this on multiple projects of different versions (5.1.1f and 5.3.3f1)
This is so annoying, could someone check this and see if it isnt just me?
The editor shows everything regardless of occlusion or draw order or everything else.
You should check the camera preview, it represents exactly what the actual game view.
Your shader(1st one) is rendered at geometry queue and it writes into zbuffer. Transparent objects usually rendered at Transparent queue and didnt write to zbuffer…
1 Like
bgolus
April 22, 2016, 7:52am
6
The skybox seems to draw differently between the scene view and game view. Mainly the skybox is drawn first in the scene view and everything else draws on top of it, but in the game view the skybox is “composited” into the scene after all opaque geometry is rendered. Specifically it appears the skybox gets rendered into the distance and gets z depth rejected by hardware. The problem is most of the matte shaders use Zwrite, which means the skybox won’t show up behind it. They don’t actually need Zwrite to be on, just the shadow caster pass needs to Zwrite, but they do need to be part of the opaque queues (2499 and below, which includes AlphaTest which is 2450) for shadow receiving to work.
1 Like
Oh my bgolus, we have progress it seems!
I thought it’s just rendering the box within the shadows, but maybe i messed up somewhere cause of some tests i did proved that to be wrong: (This is kinda big, uncompressed gif)
https://dl.dropboxusercontent.com/u/109146535/LARGE/MatteShaderBug.gif
I followed your instructions and this is what I did to the script:
Shader "Custom/ShadowDrawer"
{
Properties
{
_Color("Shadow Color", Color) = (0, 0, 0, 0.6)
}
CGINCLUDE
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f_shadow {
float4 pos : SV_POSITION;
LIGHTING_COORDS(0, 1)
};
half4 _Color;
v2f_shadow vert_shadow(appdata_full v)
{
v2f_shadow o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
half4 frag_shadow(v2f_shadow IN) : SV_Target
{
half atten = LIGHT_ATTENUATION(IN);
return half4(_Color.rgb, lerp(_Color.a, 0, atten));
}
ENDCG
SubShader
{
Tags{ "Queue" = "AlphaTest+49" }
// Depth fill pass
ZWrite Off //<------------------------ Turned off ZWriting initially
Pass
{
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f IN) : SV_Target
{
return (half4)0;
}
ENDCG
}
// Forward base pass
Pass
{
Tags{ "LightMode" = "ForwardBase" }
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert_shadow
#pragma fragment frag_shadow
#pragma multi_compile_fwdbase
ENDCG
}
// Forward add pass
Pass
{
Tags{ "LightMode" = "ForwardAdd" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite On //<--------------------------------Seems like this was where shadows were being rendered, so i renabled it here
CGPROGRAM
#pragma vertex vert_shadow
#pragma fragment frag_shadow
#pragma multi_compile_fwdbase
ENDCG
}
}
FallBack "Mobile/VertexLit"
}
What did i do wrong?
Maybe this works:
Shader "Custom/Matte Shadow" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha Cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {"Queue" = "Geometry-10" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
LOD 200
Blend Zero SrcColor
Lighting Off
ZTest LEqual
ZWrite On
ColorMask 0
Pass {}
CGPROGRAM
#pragma surface surf ShadowOnly alphatest:_Cutoff
fixed4 _Color;
struct Input {
float2 uv_MainTex;
};
inline fixed4 LightingShadowOnly (SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed4 c;
c.rgb = s.Albedo*atten;
c.a = s.Alpha;
return c;
}
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = _Color;
o.Albedo = c.rgb;
o.Alpha = 1;
}
ENDCG
}
Fallback "Transparent/Cutout/VertexLit"
}
1 Like
bgolus
April 22, 2016, 6:17pm
9
If you’re using a directional light in your scene it should be as simple as this:
Shader "Custom/MatteShadow"
{
Properties
{
_ShadowStrength ("Shadow Strength", Range (0, 1)) = 1
}
SubShader
{
Tags
{
"Queue"="AlphaTest+49"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
Tags {"LightMode" = "ForwardBase"}
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f
{
float4 pos : SV_POSITION;
SHADOW_COORDS(0)
};
fixed _ShadowStrength;
v2f vert (appdata_img v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed shadow = SHADOW_ATTENUATION(i);
fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
return fixed4(0.0, 0.0, 0.0, shadowalpha);
}
ENDCG
}
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
If you’re trying to get the shadow from a point, spot, or secondary directional light it gets a little more interesting.
1 Like
Cascho01:
Maybe this works:
Shader "Custom/Matte Shadow" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha Cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {"Queue" = "Geometry-10" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
LOD 200
Blend Zero SrcColor
Lighting Off
ZTest LEqual
ZWrite On
ColorMask 0
Pass {}
CGPROGRAM
#pragma surface surf ShadowOnly alphatest:_Cutoff
fixed4 _Color;
struct Input {
float2 uv_MainTex;
};
inline fixed4 LightingShadowOnly (SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed4 c;
c.rgb = s.Albedo*atten;
c.a = s.Alpha;
return c;
}
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = _Color;
o.Albedo = c.rgb;
o.Alpha = 1;
}
ENDCG
}
Fallback "Transparent/Cutout/VertexLit"
}
This one doesn’t seem to work in either view, makes a weird tinted spot but thats about it
bgolus:
If you’re using a directional light in your scene it should be as simple as this:
Shader "Custom/MatteShadow"
{
Properties
{
_ShadowStrength ("Shadow Strength", Range (0, 1)) = 1
}
SubShader
{
Tags
{
"Queue"="AlphaTest+49"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
Tags {"LightMode" = "ForwardBase"}
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f
{
float4 pos : SV_POSITION;
SHADOW_COORDS(0)
};
fixed _ShadowStrength;
v2f vert (appdata_img v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed shadow = SHADOW_ATTENUATION(i);
fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
return fixed4(0.0, 0.0, 0.0, shadowalpha);
}
ENDCG
}
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
If you’re trying to get the shadow from a point, spot, or secondary directional light it gets a little more interesting.
This one produces this result:
Can see the skybox in the gameview, but no shadows…
bgolus
April 22, 2016, 9:37pm
11
Right … because the skybox overwrites anything w/o zwrite. Fark, forgot about that.
Shader "Custom/MatteShadow"
{
Properties
{
_ShadowStrength ("Shadow Strength", Range (0, 1)) = 1
}
SubShader
{
Tags
{
"Queue"="AlphaTest+49"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Pass
{
Tags {"LightMode" = "ForwardBase"}
ZWrite On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f
{
float4 pos : SV_POSITION;
SHADOW_COORDS(0)
};
fixed _ShadowStrength;
v2f vert (appdata_img v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed shadow = SHADOW_ATTENUATION(i);
fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
clip(shadowalpha - 0.5);
return fixed4(0.0, 0.0, 0.0, 1.0);
}
ENDCG
}
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
That will work, but it’ll be a little ugly. The shadows have to be black and have to be hard edged. The only way around this is to not use the sky and render the background as an object in the scene (could be the same cubemap used by the skybox, it just can’t be a skybox shader).
6 Likes
bgolus:
Right … because the skybox overwrites anything w/o zwrite. Fark, forgot about that.
Shader "Custom/MatteShadow"
{
Properties
{
_ShadowStrength ("Shadow Strength", Range (0, 1)) = 1
}
SubShader
{
Tags
{
"Queue"="AlphaTest+49"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Pass
{
Tags {"LightMode" = "ForwardBase"}
ZWrite On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f
{
float4 pos : SV_POSITION;
SHADOW_COORDS(0)
};
fixed _ShadowStrength;
v2f vert (appdata_img v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed shadow = SHADOW_ATTENUATION(i);
fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
clip(shadowalpha - 0.5);
return fixed4(0.0, 0.0, 0.0, 1.0);
}
ENDCG
}
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
That will work, but it’ll be a little ugly. The shadows have to be black and have to be hard edged. The only way around this is to not use the sky and render the background as an object in the scene (could be the same cubemap used by the skybox, it just can’t be a skybox shader).
Yes!!! Thats awesome it works really well.
You actually helped me more by giving my the idea to render the skybox as a seperate object. Now all the other matte shaders work flawlessly.
Thanks a lot everyone! Especially you Bgolus
nugao
September 25, 2016, 3:26am
13
Nice…Thank you very much.
Any update on this shader to receive shadows from a point light?
bgolus:
Right … because the skybox overwrites anything w/o zwrite. Fark, forgot about that.
Shader "Custom/MatteShadow"
{
Properties
{
_ShadowStrength ("Shadow Strength", Range (0, 1)) = 1
}
SubShader
{
Tags
{
"Queue"="AlphaTest+49"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Pass
{
Tags {"LightMode" = "ForwardBase"}
ZWrite On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f
{
float4 pos : SV_POSITION;
SHADOW_COORDS(0)
};
fixed _ShadowStrength;
v2f vert (appdata_img v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed shadow = SHADOW_ATTENUATION(i);
fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
clip(shadowalpha - 0.5);
return fixed4(0.0, 0.0, 0.0, 1.0);
}
ENDCG
}
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
That will work, but it’ll be a little ugly. The shadows have to be black and have to be hard edged. The only way around this is to not use the sky and render the background as an object in the scene (could be the same cubemap used by the skybox, it just can’t be a skybox shader).
Hi bgolus,
I’m wondering if there is now a way around only using black pixels to draw the shadows on transparent surfaces to get a nicer looking shadow?
bgolus
June 27, 2018, 6:02pm
16
Yes and no. The upcoming HD pipeline comes with built in support for shadows on transparent objects. The Lightweight pipeline initially had support for this, then pulled it, but may add it again at some future date. (edit: looks like it’s working again in 2.0.3, not sure when they added it back in.)
For the built in forward rendering path nothing has changed. If you don’t use Unity’s skybox you can fake it by making an opaque object use a blend, otherwise hard shadows is the only answer.
This may seem like a silly question with an obvious answer, but how do you apply this? I’m a newbie and I was hoping I could simply render objects with cast shadows in fully HDRi scenes.
HI,
with the first version of the MatteShadow shader, I have this result :
so strenght of the shadow is adjustable but it’s doesn’t work in the game view.
With the second version of the MatteShadow shader , i have this result :
it’s now working in the game view but the shadows are not adjustable (their aspect are totally black or invisible).
Is there an ultimate solution with adjustable shadow that’s works in the game view with a skybox ?
Thank you
I note that behind an object which has this shader, all non opaque objects (for example which has a unity standard shader but with its rendering mode set to transparent) are invisible.
Any idea about this “phenomenom” ?
This works perfectly when I run it in the editor but when I test it on Oculus Quest 2, there are no shadows. Does anyone know why?