U3: Add 2 sided to AlphaTest-Bumped.shader?

I need a 2-sided cut-out transparent, diffuse bumped shader. I looked at some of the other 2-sided shaders posted here in the forums, but they don’t seem to work in Unity 3.0. Any ideas? Here is the original shader:

Shader "Transparent/Cutout/Bumped Diffuse" {
Properties {
	_Color ("Main Color", Color) = (1,1,1,1)
	_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
	_BumpMap ("Normalmap", 2D) = "bump" {}
	_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}

SubShader {
	Tags {"IgnoreProjector"="True" "RenderType"="TransparentCutout"}
	LOD 300
	
CGPROGRAM
#pragma surface surf Lambert alphatest:_Cutoff

sampler2D _MainTex;
sampler2D _BumpMap;
float4 _Color;

struct Input {
	float2 uv_MainTex;
	float2 uv_BumpMap;
};

void surf (Input IN, inout SurfaceOutput o) {
	half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
	o.Albedo = c.rgb;
	o.Alpha = c.a;
	o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}

FallBack "Transparent/Cutout/Diffuse"
}

Have you considered doubling your geometry? It’s way easier and usually performs better.

I want to use it on an interactive cloth object.

Ah. That’s a good reason to do it in a shader.

Unfortunately, I think might be pretty horrible to do. I would approach it by compiling the above shader with #pragma debug. This will give you the passes generated by the surface shader translator. Then you need to duplicate all of those passes and negate the normals in the duplicates.

I’m not actually sure how that will work with lighting passes.

I’m about as far from a shader coder as you can get. I think I modified a grand total of one shader without breaking it. :wink: Maybe one of those new visual shader editors might be easier for me to work with…

Ok wait I figured out a far easier way to do it. It requires two materials: the built-in one and this, slightly modified one:

Shader "Transparent/Cutout/Bumped Diffuse Backwards" {
Properties {
	_Color ("Main Color", Color) = (1,1,1,1)
	_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
	_BumpMap ("Normalmap", 2D) = "bump" {}
	_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}

SubShader {
	Tags {"IgnoreProjector"="True" "RenderType"="TransparentCutout"}
	LOD 300
	Cull Front
	
CGPROGRAM
#pragma surface surf Lambert alphatest:_Cutoff

sampler2D _MainTex;
sampler2D _BumpMap;
float4 _Color;

struct Input {
	float2 uv_MainTex;
	float2 uv_BumpMap;
};

void surf (Input IN, inout SurfaceOutput o) {
	half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
	o.Albedo = c.rgb;
	o.Alpha = c.a;
	o.Normal = -UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}

FallBack "Transparent/Cutout/Diffuse"
}

Then, on your cloth, make the Materials array have a length of 2 instead of 1. Use the built-in shader for the first one, and the fancy new backwards shader for the second one.

Note that all I did was add Cull Front before the CGPROGRAM block, and a minus sign in front of UnpackNormal().

Thank you so much Daniel, this is working absolutely perfectly! :slight_smile:

A simple CULL OFF would disable backface culling the simple way. Daniels solution however has the charme of correctly aligned normals. But wouldn’t it be faster to do all the stuff in a second pass as only one draw call would be required?

Cull Off produces reversed lighting. The second material is the only way to use the normals correctly, although both approaches break shadows in forward rendering.

What do you mean by “all the stuff”?

Actually, I’m quite happy with Daniel’s solution. Works great and I haven’t seen any appreciable performance lost (although I haven’t really done any super accurate performance tests).

Hi, I’m sorry to jump in like this, I’ve been in need of a shader like this for cloth precisely and this sounds great, but I have a question, I’m really no programmer so could someone please explain the part where Daniel, says

I would really appreciate it. Thx!

Ok nevermind that, I figured it out. Still thx for the shader!

Daniel,

Thanks so much for your shader solution and help on the forums. It’s a shame that the Unity team hasn’t posted an AAA tutorial about the Interactive Cloth features and possibilities, but through the community I have been able to figure out most of the details to mae it work. Anyway, your shader works perfectly and looks good. I hope to be able to upload some screenshots of the prototypes I’m working on soon. Thanks again for the help and the shader code.

Cheers!
-arbbot

I have a problem with above shader. It’s working great on meshes, but on Cloth objects it’s just flipping normals and front side become invisible.( Any way to fix this?

Did you follow the instructions given with the shader?

Ok guys,

Thanks a lot for this very usefull Thread.
Starting from this, I went a little bit further with a case study (a waving flag shader).

Full documentation here :
http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/

It covers the following points :

    • Flag vertices animation via a shader (trigo. way)
    • Advanced ShaderLab surface shading for transparency management
    • Adding a shadow Pass (with alpha support)
    • Double-sided surfaces methods (methods 1, 2 and 3)
    • Provided Double-sided Materials Configuration Wizard (for 3rd method)

Downloads [from the address bellow]

    • PDF version of the article : WavingFlag.pdf
    • Configuration Wizard : BackwardMaterialBuilder.cs
    • Unity 3.3 Package : WavingFlagDemo.unitypackage | WavingFlagDemo.rar

Here is my shader code :

The “FlagWaveCG.cginc” 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
// 
// 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.  
// 
// [url]http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/[/url] ] for
// visuals and more informations


#include "UnityCG.cginc"

float4 _Color; 
sampler2D _MainTex;
fixed _Cutoff;
float _WaveSpeed;
float _WaveStrength;


struct v2f { 
	V2F_SHADOW_CASTER; 
	float2 uv : TEXCOORD1;
};


void computeWave (inout appdata_full v, inout v2f o)
{
	float sinOff=(v.vertex.x+v.vertex.y+v.vertex.z) * _WaveStrength; 
	float t=-_Time*_WaveSpeed; 
	float fx=v.texcoord.x; 
	float fy=v.texcoord.x*v.texcoord.y; 

	v.vertex.x+=sin(t*1.45+sinOff)*fx*0.5; 
	v.vertex.y=(sin(t*3.12+sinOff)*fx*0.5-fy*0.9); 
	v.vertex.z-=(sin(t*2.2+sinOff)*fx*0.2); 
	o.pos = mul( UNITY_MATRIX_MVP, v.vertex ); 
	o.uv = v.texcoord;
}

The “FlagWave-Advanced.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
// 
// 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" 
{ 

Properties 
{ 
 	// Ususal 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"}

	LOD 300



	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
}
	
Fallback "Transparent/VertexLit"
}

Hope this will help…

Hi !

I try your SHADER “Selfmade/TransparentShadowCaster”, but it dosen’t work :face_with_spiral_eyes:

Can you help me to see the shadows on my plane with an alpha texture ?

Many thanks for yout help ! :wink:

Hello,

I made some tests and it appears that it works with Point and Spot Lights, but no satisfying result with a “Directional Light”.
Does anyone has an idea about this issue ?
Thanks

NB : Here is what I get with a “Spot Light” dedicated to the “alpha plane” layer >>

A workaround to all of this could be :

Apply 2 materials to the Plane >>

  1. One as described above (TransparentShadowCaster)
  2. A second one to obtain the shadow working with “Directional Light” (using “Transparent/Cutout/Diffuse” built-in shader, which can handle shadows receiving)

Illustration [Not very satisfying because of the aliasing at the shadow border] :

Obtained with the following settings :

But well, I don’t have any better simple solution right now… And what about you, guys ?

Try adding addshadow to the pragma line.

Already tested with no result
Thanks