Ah okay, i’m sorry. Just read through the code. The receiving part is alpha, not alpha testing so it will never ever receive shadows. If you can switch it to cutoff, you could get shadows otherwise it won’t work.
Ok, we went to the same conclusion : “Cutoff” is the only way. But what I would really like to know is the big difference between Spot/Point lights and Directional ones (just for Unity knowledge purpose). Why can I get a perfect result with the first ones and nothing at all with the second ones ?
NB : A little amelioration for the “cutout/cutoff solution” : using the AntiAliasing Post Effect (DLAA technique) given with the “Image Effects (Pro Only)” package. But we still have un-shadowed (white) edges - of course.
(And of course, it is costly, real-time computing speaking ! But can be OK for small scenes…)
So, I went a little further and found the LightMode" = “ForwardBase” Pass Tag.
This does : “Used in Forward rendering, ambient, main directional light and vertex/SH lights are applied”.
http://unity3d.com/support/documentation/Components/SL-PassTags.html
With this tag added to our shader, then only the main directional light is used, taking ride of the others.
Here comes the modified shader [FlagWave Advanced Regular - ForwardBase] :
// Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
// Original shader by cboe - Mar, 23, 2009
// Enhanced to 3 axis movement by Seon - Jan, 21, 2010
// Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
// CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
// - Added Transparency support
// - Added Spec and Normal mapping support
// - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
// [Done in the "ShadowCaster" additional Pass]
// - Added advanced double-sided rendering support
// - Added _WaveStrength param
//
// Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
// Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.
//
// See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
// visuals and more informations
Shader "Selfmade/for-2sided/FlagWave Advanced Regular - ForwardBase"
{
Properties
{
// Usual stuffs
_Color ("Main Color", Color) = (1,1,1,1)
_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
_MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
// Bump stuffs
//_Parallax ("Height", Range (0.005, 0.08)) = 0.02
_BumpMap ("Normalmap", 2D) = "bump" {}
//_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
// Shadow Stuff
_Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
// Flag Stuffs
_WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
_WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
}
SubShader
{
Tags {
"Queue"="Geometry"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"LightMode" = "ForwardBase" }
LOD 300
// Removed
/*
Pass
{
Name "ShadowCaster"
.
.
.
}
*/
//CULL Front
CGPROGRAM
#pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
#include "FlagWaveCG.cginc"
half _Shininess;
sampler2D _BumpMap;
//sampler2D _ParallaxMap;
float _Parallax;
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
//float3 viewDir;
};
v2f vert (inout appdata_full v) {
v2f o;
//computeWave(v, o);
return o;
}
void surf (Input IN, inout SurfaceOutput o) {
// Comment the next 4 following lines to get a standard bumped rendering
// [Without Parallax usage, which can cause strange result on the back side of the plane]
/*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
IN.uv_MainTex += offset;
IN.uv_BumpMap += offset;*/
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = tex.rgb * _Color.rgb;
o.Gloss = tex.a;
o.Alpha = tex.a * _Color.a;
//clip(o.Alpha - _Cutoff);
o.Specular = _Shininess;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}
//Fallback "Transparent/VertexLit"
FallBack "Diffuse"
}
Starting from that point, we can then combine both Directional and Spot/Point lights :
Here come the materials settings :
Any comment or nicer solution (using one single Surface Shader, by example) are welcome.
Thanks
Does anyone has an idea on how to merge the 2 shaders into a single one ?
Shader 1 : http://forum.unity3d.com/threads/61882-U3-Add-2-sided-to-AlphaTest-Bumped.shader?p=577273&viewfull=1#post577273
Shader 2 : http://forum.unity3d.com/threads/61882-U3-Add-2-sided-to-AlphaTest-Bumped.shader?p=696649&viewfull=1#post696649
Any help/suggestion will be appreciated.
Many thanks.
Here is the shader code for a first attempt to get rendered both Spot/Point light and Directional shodows :
[It consists in adding the shadows generated by the Directional light by blending the light attenuation over the rest…]
// Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
// Original shader by cboe - Mar, 23, 2009
// Enhanced to 3 axis movement by Seon - Jan, 21, 2010
// Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
// CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
// - Added Transparency support
// - Added Spec and Normal mapping support
// - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
// [Done in the "ShadowCaster" additional Pass]
// - Added advanced double-sided rendering support
// - Added _WaveStrength param
//
// Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
// Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.
//
// See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
// visuals and more informations
Shader "Selfmade/for-2sided/FlagWave Advanced Regular - ForwardBase - Single"
{
Properties
{
// Usual stuffs
_Color ("Main Color", Color) = (1,1,1,1)
_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
_MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
// Bump stuffs
//_Parallax ("Height", Range (0.005, 0.08)) = 0.02
_BumpMap ("Normalmap", 2D) = "bump" {}
//_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
// Shadow Stuff
_Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
_ShadowIntensity ("Shadow Intensity", Range (0, 2)) = 0.6
// Flag Stuffs
_WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
_WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
}
SubShader
{
Tags {
"Queue"="Geometry"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
LOD 300
//Lighting On
/* Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
Fog {Mode Off}
ZWrite On ZTest Less Cull Off
Offset 1, 1
CGPROGRAM
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
#pragma exclude_renderers gles
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile_shadowcaster
#include "FlagWaveCG.cginc"
v2f vert( appdata_full v )
{
v2f o;
///computeWave(v, o);
TRANSFER_SHADOW_CASTER(o)
return o;
}
//sampler2D _MainTex;
float4 frag( v2f i ) : COLOR
{
fixed4 texcol = tex2D( _MainTex, i.uv );
clip( texcol.a - _Cutoff );
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
//SetTexture [_MainTex] {combine texture}
} */
//CULL Front
CGPROGRAM
#pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
#include "FlagWaveCG.cginc"
half _Shininess;
sampler2D _BumpMap;
//sampler2D _ParallaxMap;
float _Parallax;
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
//float3 viewDir;
};
v2f vert (inout appdata_full v) {
v2f o;
//computeWave(v, o);
return o;
}
void surf (Input IN, inout SurfaceOutput o) {
// Comment the next 4 following lines to get a standard bumped rendering
// [Without Parallax usage, which can cause strange result on the back side of the plane]
/*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
IN.uv_MainTex += offset;
IN.uv_BumpMap += offset;*/
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = tex.rgb * _Color.rgb;
o.Gloss = tex.a;
o.Alpha = tex.a * _Color.a;
//clip(o.Alpha - _Cutoff);
o.Specular = _Shininess;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
// We "add" the shadows by blending the light attenuation
Pass {
Blend SrcAlpha OneMinusSrcAlpha
Name "ShadowPass"
Tags {"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma exclude_renderers xbox360
#pragma debug
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f {
float2 uv_MainTex : TEXCOORD1;
float4 pos : SV_POSITION;
LIGHTING_COORDS(3,4)
float3 lightDir;
};
uniform float4 _MainTex_ST;
uniform sampler2D _MainTex;
uniform float4 _Color;
uniform float _ShadowIntensity;
v2f vert (appdata_full v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.lightDir = ObjSpaceLightDir( v.vertex );
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
float4 frag (v2f i) : COLOR
{
float atten = LIGHT_ATTENUATION(i);
half4 c;
c.rgb = 0;
c.a = (1-atten) * _ShadowIntensity * tex2D(_MainTex, i.uv_MainTex).a;
return c;
}
ENDCG
}
}
//Fallback "Transparent/VertexLit"
FallBack "Diffuse"
}
It gives :
Well, I’m unsatisfied because of the darkening all over the holes in the main texture.
(It was not the case with the method explained bellow : http://forum.unity3d.com/threads/61882-U3-Add-2-sided-to-AlphaTest-Bumped.shader?p=696649&viewfull=1#post696649).
I tried to get ride of it by doing :
c.a = (1-atten) * _ShadowIntensity * tex2D(_MainTex, i.uv_MainTex).a;
But it seems that the tex2D(_MainTex, i.uv_MainTex).a doesn’t reduce the intensity of the shadow even where pixels are fully transparent from the main texture (I think that I don’t get the right alpha informations from the texture).
Any idea ?
Thanks again.
Well, I found out something. And yes I didn’t get the right alpha informations from the main texture :
Just added this line in the “vert” function :
o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
“TRANSFORM_TEX” calculates the uv coordinates for the tiling and offset set up for the texture…
Shame on me !
It looks quite good now :
Full final shader file :
// Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
// Original shader by cboe - Mar, 23, 2009
// Enhanced to 3 axis movement by Seon - Jan, 21, 2010
// Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
// CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
// - Added Transparency support
// - Added Spec and Normal mapping support
// - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
// [Done in the "ShadowCaster" additional Pass]
// - Added advanced double-sided rendering support
// - Added _WaveStrength param
// - Added full support for Shadow receiving
// [Done in the "ShadowPass" additional "ForwardBase" Pass]
//
// Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
// Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.
//
// See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
// visuals and more informations
Shader "Selfmade/for-2sided/FlagWave Advanced Regular - ForwardBase - Single"
{
Properties
{
// Usual stuffs
_Color ("Main Color", Color) = (1,1,1,1)
_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
_MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
// Bump stuffs
//_Parallax ("Height", Range (0.005, 0.08)) = 0.02
_BumpMap ("Normalmap", 2D) = "bump" {}
//_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
// Shadow Stuff
_Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
_ShadowIntensity ("Shadow Intensity", Range (0, 2)) = 0.6
// Flag Stuffs
_WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
_WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
}
SubShader
{
Tags {
"Queue"="Geometry"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
LOD 300
//Lighting On
/* Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
Fog {Mode Off}
ZWrite On ZTest Less Cull Off
Offset 1, 1
CGPROGRAM
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
#pragma exclude_renderers gles
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile_shadowcaster
#include "FlagWaveCG.cginc"
v2f vert( appdata_full v )
{
v2f o;
///computeWave(v, o);
TRANSFER_SHADOW_CASTER(o)
return o;
}
//sampler2D _MainTex;
float4 frag( v2f i ) : COLOR
{
fixed4 texcol = tex2D( _MainTex, i.uv );
clip( texcol.a - _Cutoff );
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
//SetTexture [_MainTex] {combine texture}
} */
//CULL Front
CGPROGRAM
#pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
#include "FlagWaveCG.cginc"
half _Shininess;
sampler2D _BumpMap;
//sampler2D _ParallaxMap;
float _Parallax;
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
//float3 viewDir;
};
v2f vert (inout appdata_full v) {
v2f o;
//computeWave(v, o);
return o;
}
void surf (Input IN, inout SurfaceOutput o) {
// Comment the next 4 following lines to get a standard bumped rendering
// [Without Parallax usage, which can cause strange result on the back side of the plane]
/*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
IN.uv_MainTex += offset;
IN.uv_BumpMap += offset;*/
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = tex.rgb * _Color.rgb;
o.Gloss = tex.a;
o.Alpha = tex.a * _Color.a;
//clip(o.Alpha - _Cutoff);
o.Specular = _Shininess;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
// Adding the shadows (from Directional Light)
// by blending the light attenuation
Pass {
Blend SrcAlpha OneMinusSrcAlpha
Name "ShadowPass"
Tags {"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma exclude_renderers xbox360
#pragma debug
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f {
float2 uv_MainTex : TEXCOORD1;
float4 pos : SV_POSITION;
LIGHTING_COORDS(3,4)
float3 lightDir;
};
float4 _MainTex_ST;
sampler2D _MainTex;
float4 _Color;
float _ShadowIntensity;
v2f vert (appdata_full v)
{
v2f o;
o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.lightDir = ObjSpaceLightDir( v.vertex );
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
float4 frag (v2f i) : COLOR
{
float atten = LIGHT_ATTENUATION(i);
half4 c;
c.rgb = 0;
c.a = (1-atten) * _ShadowIntensity * (tex2D(_MainTex, i.uv_MainTex).a);
return c;
}
ENDCG
}
}
//Fallback "Transparent/VertexLit"
FallBack "Diffuse"
}
Well, I agree with it. And my final solution is only available for “Forward” rendering path (this can be a constraint for many different reasons - and a benefit for some others).
What ever your needs are : here is the document I produced covering what we’ve been talking about until now : http://klakos.com/en/fully-shadowed-transparent-shader-for-unity-shadows-receiving-support-from-spotpoint-and-directional-lights/
Guess this will be useful for some of you !
Hi. Cool stuff, i’ll read through all of that later. Maybe quite useful, so thanks for it.
Regarding the “only in forward path”-thing, it looks like there’s a bug in unity itself, preventing things from casting/receiving full shadows in deferred rendering, when they are drawn in forward mode (which is the case for transparent objects and all shaders using a modified lighting function). Already reported this, but sadly haven’t got any replies or info on that.
Ok, good to know. Very interesting informations [Coming from a “Shader lord” : I had a look to your Shader Bundle, and they’re impressive (specially the skin ones are so awesome).]
Thanks a lot.
Well, to make sure that I fully understood what you said : Do you mean that everything that works and is drawn in forward mode should also theoretically work (cast/receive shadows) in deferred ? Is it the way it works in the others game engines ?
Edit : I saw that you forced all your shaders (from the Chicken Bundle) in forward mode… What kind of differences can we get with them by switching the rendering path from forward to deferred ?
Despite transparent objects: Yes. Transparent objects don’t cast or receive shadows because they do not write to the depth buffer.
It’s not me who forces them to be drawn in forward mode but the engine itself. Here’s how it works.
In deferred lighting all the lighting stuff is done in screen space. But it has a major disadvantage, which is that all objects are using the same lighting function (usually Blinn-Phong). While is performance wise a good choice, it obviously prevents you from using a different lighting function for some objects (as long as it’s not just a slightly changed one).
Then you have three ways to solve this issue. You could either use deferred shading, which is way more powerful but also needs way more performance. Lately there are more and more papers on how to implement deferred shading efficiently etc, so it will probably become the standard in next few years (as long as no other incredible technique shows up).
Another way would be to extend the G-Buffer, in order to allow all the different lighting things. This kills one of the main benefits of deferred lighting though, the small G-Buffer, and in addition you’d have to compute all the lighting for all the objects regardless of what kind of light they use. So, for example, you’d calculate the light traveling inside an object to render translucency although the objects isn’t translucent at all. (I may be mistaken with this one, so if i am and your reading this, please correct me)
The last possibility, which unity actually uses, is to draw everything in deferred mode, that can be drawn in deferred mode. So in a usual case, all that stuff that isn’t transparent (cut-off should work if i’m correct) and uses a deferred lighting compatible light model, so Blinn-Phong or slightly changed Blinn-Phong. Everything else is drawn in forward mode. Regarding the fact how unity solves the mixing of those two renderers, i don’t know.
So the issue here is, that all my shaders use a completely different lighting function. So they are drawn in forward mode. And they do receive/cast shadows in deferred rendering. But they only receive shadows from the most important light of a type in a scene. So if there are for example three directional lights, all three are taken into account for the model lighting itself but only the most important one (usually the brightest one) does cast shadows onto the custom shader material.
I don’t know, what the issue for this really is, but this doesn’t happen in forward mode. So yeah, i don’t know if this is a general Unity bug, if it does only happen for me, or if this is done on purpose.
And now that i’m finished writing i have the feeling i forgot something and said a whole bunch of stupid nonsense
(but i guess it’s not that bad)
Ok “Chickenlord”,
First of all, thank you so much for having taken so much time to explain all of this. And don’t worry : Everything you said makes definitely sense to me and is an excellent starting point for me to pick up more informations by googling, concerning some of the points you’ve been talking about. So thank you so very much !
Yes you are correct.
So do I ! For example I’ve been able to get this in Deferred Lighting by heavily tricky tricky way and it does probably make sense to Unity programmers but definitely not to me ( (using 2 cameras - one [CullingMask = Everything, Depth Only] for the transparent plane, another one [CullingMask = exclude transparent plane layer, Skybox]) + (playing with Queue and RenderType Tags) - and 2 lights : spot + directional [directional blended using ForwardBase like explained earlier] ) :
Both Cameras turned into Deferred L
Anyway it is not exploitable… And it seems to make the renderer a bit crazy in the Game view, even if it works perfectly in play mode.
But now, I think I have a better understanding about how Unity behaves, renderly and shaderly speaking
.
Interesting solution, but I’m wondering how I could use that on a multi-material model? I have two materials on that model, one of which is supposed to have a two-sided material with flipped normals on the backside. In Blender, the two materials are assigned to their respective faces and correctly show up in Unity. However, if I simply add another material slot to the mesh renderer, how will Unity know what faces to assign the new material to?
Can anyone get this to work with Unity5 ?