Backface Culling Unity / transparency shaders

edited in Questions and Answers
Howdy,

What I'm trying to find out is how to get backface culling turned off inside unity.
So that when I have a plane with an alpha texture and a transparent shader applied to it, as the camera sees the other side of the plane it stays visible.

Unity forums are suggesting adding some code to the shader to turn the culling off?
or
doubling up the faces with the normals facing the other way, which apparently is has less of a performance hit than the culling off option?

There are roughly 20 faces that would be doubled up, or not culled which doesn't seem to be that big a deal in terms of performance, but then again I have no clue.

The second issue is the actual shaders.
The current one that's giving me the effect that I want is: Transparent/Cutout/Soft Edge Unlit, but I don't know how that's going to affect the performance on mobile devices, or if it's even possible to have non mobile shaders work on android devices.

Also, would it be common practice to have all the geometry as one piece (that could only have 1 material) or to have two separate pieces, one that just has a normal mobile diffuse and the second that has the transparency shader?


So to recap:
How do you deal with back face culling, wanting 2 sided objects with one face?
and
what transparent shaders are best for mobile development?

Thanks in advance.

-P

Comments

  • I had a similar issue a while back. I didn't even think it through as far as you have. I just stuck two objects to each other to get an image from the back. I'm not that versed in shaders and textures so I didn't really have any other choice, but it did work the way I wanted it to in the end.

    As for the perfomance, I guess you could just build a few prototypes that test the specific shaders and check how they measure up against each other?
  • Cool, thanks dude. My gut feeling was to go the double up on faces, seemed the easiest and fastest solution to implement.
  • Heyyy! :)
    How do you deal with back face culling, wanting 2 sided objects with one face?
    You're right in that you can either change this in the shader (First download the built in shader source from here, then find the shader you want to edit, and stick "Cull Off" without quotes inside the SubShader) or in your mesh. Either way can be preferable depending on the context.

    The duplicated flipped faces is usually better, because then you can choose which faces you want to be double-sided. But if you're sure that all of the mesh should be double-sided then editing the shader is more convenient, because if you make any changes to the mesh, you don't have to keep making sure that your doubled faces are snapped together.
    what transparent shaders are best for mobile development?
    I don't know about this specific shader (I don't have much experience with how the default shaders work), but as far as I know soft edged shaders require rendering a depth pass, which is only (freely) available in deferred rendering. You probably won't be able to use that shader on mobile unfortunately. If you need soft edged transparency, you may be able to work around it using alpha based on fresnel instead of depth. Some things just aren't possible/feasible on mobile though, and if your transparent mesh is intersecting with something else, you'll pretty much always see a hard edged break.
    Also, would it be common practice to have all the geometry as one piece (that could only have 1 material) or to have two separate pieces, one that just has a normal mobile diffuse and the second that has the transparency shader?
    I think it'd be better to have only the bits that need transparency using a transparent shader. That way, you decrease the chance of some kind of alpha-sorting issues, and you decrease the expense of rendering the opaque bits.
    Thanked by 1Chippit
  • As a rule, don't even consider using ANY provided shader from Unity unless it is inside of the "Mobile" shader folder. They have all been optimised heavily for mobile GPUs unlike all of the other Unity shaders. That doesn't mean that they are all cheap though; something like bump spec is going to be expensive on your fillrate no matter how optimised it is :)
  • (@Elyaradine omg was looking for the Unity shader sources just the other day! Many thanks for the link!)
  • Wow, thanks for the detailed response @Elyaradine!
    I'm pretty happy with the double faces, but definitely want to try out the shader options, just to see what happens to performance :)
  • Hi,
    Just happen to hit this with a Google search on finding the solution myself.
    Here is a Unity forum thread that has the solution in with a download link to the shader you would want to use.

    http://forum.unity3d.com/threads/93189-Two-sided-cutout-shader-for-U3-wanted

    Cheers
  • @Elyaradine has pretty much answered this conclusively, but there's one more thing to bear in mind that I don't see mentioned here:

    The doubling of faces in your mesh is indeed a simple (and selective) solution to the problem, but it's something you should avoid on skinned meshes. The CPU hit per vert for mesh skinning is one of the most expensive things your game will do for animated actors (on mobile - newer versions of Unity support GPU skinning on desktop platforms and some Androids), and if you're going to double that per character, you're going to hurt unnecessarily.

    Now, I see this is not the case with your situation, but I thought it important to mention this in the event someone else refers to this thread for other situations. The takeaway: if you're skinning and need to draw backfaces (cloth?), you probably want take the 'hit' on the GPU instead and turn backface culling off in your shader.
  • We had a similar problem. I ended up writing our own shaders, A few different ones for alphas and depth traced alphas. As the main problem with a transparent shader is that if will get sorted incorrectly when drawn on screen.

    I would suggest using these shaders also sparingly as a transparent sorted shader has large overhead costs, but that being said we use it a ton and it works and isn't to much of a hog on iOS platform.

    http://docs.unity3d.com/Documentation/Components/SL-AlphaTest.html

    This shows you how to take into account the depth with transparency, and have it tweakable live.

    Be warned that different shaders play differently, in a horrible way. a transparent shader infront of a none transparent unsorted shader will disappear from ones view, as it is being drawn on screen, but been drawn behind the object which is actually behind it.

    also if you want to use a color override with alphas be careful, as some depth sorting transparent shaders wont allow for this and you end up with popping from visible to invisible.
  • Heres a backfaced, depth traced, unlit shader if anyone would like, you may use it for commertial games, just please dont sell the shader itself.

    It will appear under shaders/doubleSided/

    // Developed by SIJO STUDIOS Pty Ltd
    // Developer: Simon Anderson
    // Version: 1.2
    Shader "SIJO/doubleSided/Unlit_AlphaCutOff"
    {
    Properties
    {
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    _ColorTint ("Tint", Color) = (1.0, 1.0, 1.0, 1.0)
    _Cutoff ("Alpha cutoff", Range (0,1)) = 0.5
    }
    SubShader
    {
    Tags { "RenderType" = "Transparent" }

    //used for backface culling
    Cull Off

    // Surface shaders are placed between CGPROGRAM and ENDCG
    // - They use #pragma to let unity know its a surface shader
    // - Must be in a SubShader block
    CGPROGRAM
    #pragma surface surf Unlit alphatest:_Cutoff
    struct Input
    {
    float2 uv_MainTex;
    };
    sampler2D _MainTex;

    // applies a color tint to the shader
    fixed4 _ColorTint;

    half4 LightingUnlit(SurfaceOutput s, half3 lightDir, half atten)
    {
    return half4(s.Albedo, s.Alpha);
    }

    // applies the texture to the UV's
    void surf (Input IN, inout SurfaceOutput o)
    {
    fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _ColorTint;
    o.Albedo = c.rgb;
    o.Alpha = c.a;
    }
    ENDCG
    }
    }
  • You could optimize that shader for mobile a bit by:

    -Using half for the input UVs
    -Using fixed for your lightDir if it is normalized
    -Using fixed for the color returned from LightingUnlit

    Also know that alpha cutoff is super expensive on TBDR gpus like the PowerVR ones used in iOS devices. If you need it you need it, but it's cheaper to do standard alpha blending if you can.
  • Thanks AngryMoose will take a look this weekend :D
  • Just did a massive rewrite in the week of all our shaders, and here is a pretty generic one for everyone. You can pick it apart.

    Shader "SIJO/Single_Sided/Flat_Texture_noZ_color_tint_transparent" //Name of the shader
    {
    	Properties // This is a properties block, where you create properties that will be used in the shader
    	{
    		_Color ("Main Color", Color) = (1.0,1.0,1.0,1.0)  // '_' variables that can be adjusted in unity, self name tracking
    		_ColorTint ("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
    		_MainTex ("Diffuse Texture", 2D) = "white"{}
    	}
    	
    	// Subshader contains the shader
    	SubShader
    	{
    		Tags { "Queue" = "Transparent" } // Tells Unity to render this in the transparent queue, this stops flickering
    		Blend srcAlpha oneMinusSrcAlpha
    		// Pass is like a render pass in Maya/Softimage
    		Pass
    		{			
    			AlphaTest Off
    			Lighting Off
    			zWrite OFF
    			
    			// Everything outside of CGProgram is Shaderlab language
    			CGPROGRAM // Is the language writen by NVIDIA
    			
    			//pragmas
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			//user defined variables
    			//uniform fixed4 _Color;  	//uniform is a CG specific keyword, used to define variables, Unity doesn't need it			
    			uniform sampler2D _MainTex;
    			uniform half4 _MainTex_ST;
    			uniform half4 _Color;
    			uniform half4 _ColorTint;
    			
    			
    			//base input structs
    			// structs are like base class's
    			struct vertexInput
    			{
    				half4 vertex : POSITION; // Assigns the vertex possition to a vertex variable								
    				half4 texcoord : TEXCOORD0;
    			};
    			
    			struct vertexOutput
    			{
    				half4 pos : SV_POSITION; // Needed for DX11
    				half4 tex : TEXCOORD1;								
    			};
    						
    			//vertex function
    			
    			vertexOutput vert(vertexInput v) //writing to vertexOutput, vert is the new name ifunctiont
    			{
    				vertexOutput o;	 // is the same as o = vertexOutput				
    				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    								
    				o.tex = v.texcoord;
    								
    				return o;			
    			}
    			
    			//fragment functions
    			
    			fixed4 frag(vertexOutput i) : COLOR
    			{			
    				//Texture Maps
    				fixed4 tex = tex2D(_MainTex, i.tex.xy * _MainTex_ST.xy + _MainTex_ST.zw);							
    				return fixed4( tex.xyz * _ColorTint.xyz + _Color.xyz, tex.a * _Color.a * _ColorTint.a);
    			}
    			
    			ENDCG
    		}
    	}
    	// fallback commented out during development
    	//Fallback "Flat" // this incase your shader errors out it will use this instead
    }


    It basically is a double sided, unlit, transparent shader with color addition and color tinting.

    Hope this helps someone out there
Sign In or Register to comment.