Transparent shader in background queue

Hello Unity fellows,

I have a hard time trying to render a transparent object in the “Background” queue. I spent one day searching Unity Forums and Answers for hints, but everything I tested wasn’t successful. A bit of a context (because the problem may be complex):

I have an outside environement with sea and sky. I use the “Blended SkyBox” shader to create a skybox, and, I want to add a sun (simple quad with texture). I don’t want to use a “far away” object because it requires to have a far away clipping plane, and it is always possible to spot the trick when the sun sets above the sea if the camera is quite high (you see the sun going “through the sea”, not “behind”).

Thus, I just want to render my sun behind everything, except the sky (rendered in Queue = Background), ie using a Queue=“Background+1” tag. Problem is, my sun is round, and thus, my texture is transparent.

I use the following “simple” shader:


Shader "Custom/SunAndMoon" {
	
    Properties
    {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB) Trans. (Alpha)", 2D) = "white" { }
    }

	 SubShader
    {
        
        Tags {"Queue"="Background+1" } // OK for Queue=2500 or +. Below, it doesn't work.
     	Cull Off
        Fog { Mode Off }
        Blend SrcAlpha OneMinusSrcAlpha
           
        Pass
        {
            Lighting Off
            SetTexture [_MainTex]
            {
                constantColor [_Color]
                Combine texture * constant, texture * constant 
            } 
        }
    } 
}

Actually this shader gives this render:

Funny thing is, if I change the Queue to “Background+1501” it works (Alpha blending is taken into account, see this render:

But it renders the sun after all Geometry, which I don’t want. If Queue is “Background +1500” or lower, Alpha Blending doesn’t work.

It seems that Queues do additionnal stuff appart from managing rendering order.

Other tests I made:

  • Using a cutout (AlphaTest Greater 0.2) in Queue = Background+1 → OK, But I’d like to have the “glow” effect achieved with alpha blending
  • Disabling skybox, enabling Alpha blending and Queue = Background+1 → OK
    This tends to show that the problem is not really with alpha blending but rather with getting the “destination color”. With a solid clear color, it’s OK. With a skybox it’s not, we get that “dark grey color” around the sun spot. Talking about it…
  • …The “black” around the sun is not pure black. It’s some dark grey which might be used by unity to “clear” the viewport. It’s NOT related to ambient light, and NOT related to the “clear color” specified in the camera settings (this drives me crazy). I can see it by turning my skybox alpha to 0.
  • Enabling skybox and Alpha Blending, Queue = Background+1, Disabling ZWrite (because at some point, I’ll have to)-> The sun is not visible anymore! But actually, by playing with the skybox alpha, it appears that the sun is rendered BEHIND the sky…
  • Trying to use a vertex/fragment shader instead of my fixed pipeline shader seemed to work at some point. But when I restarted Unity, the same problem raises again. It may be influenced by shaders order in memory I guess.

Those results don’t make any sense at all for me. I must have missed something.
Any help from Unity gurus would be greatly appreciated.

Thanks a lot :slight_smile: and sorry for the long explanation.

Okay! I’m finally back with some kind of solution.
I hope this can help some of you out there with the same problem!

I recently made a few bunch of tests on this problem, and I found that the problem doesn’t come from the sun shader, but from the use of the standard skybox of Unity.
For some reason, be it the skybox of the Render Settings or the Skybox component on a camera, the rendering of the skybox seems to affect the rendering of following transparent elements in the background queue.

Indeed, when I use a custom-made skybox, everything is OK.
Here’s what I did:

  1. Disable all unity skyboxes (Render
    Settings and Skybox component of the
    camera) and set the background of the camera to “solid”
  2. Create a sphere centered on the camera and parent it to the camera
  3. Remove the collider of the sphere, and attach a script which constantly sets the rotation of the sphere to Quaternion.identity
  4. Attach a personal skybox material to
    the sphere with the shader below
  5. Finally use the sun shader in Background Queue +1 for example, and transparency works well!

This may not be the best shader, but it works:

Shader "Custom/cubemapSkybox" 
            {
            	Properties {
            		_CubeDay("CubeMap Day", CUBE) = "" {}
            	}
            	SubShader 
            	{
            		Tags { "Queue"="Background" "RenderType"="Background" }
        		
        		LOD 200
        		Cull Off
        		ZWrite Off
        		Pass 
        		{
        			CGPROGRAM
        			#pragma vertex vert
        			#pragma fragment frag
        	     	#include "UnityCG.cginc"
        	
        			samplerCUBE _CubeDay;
        			
        			struct v2f 
        			{
        	            float4  pos : SV_POSITION;
        	            float3 norm : TEXCOORD0;
        	        };
        	 		v2f vert (appdata_base v)
        			{
        				v2f o;
        				o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
        				o.norm = v.normal;
        				return o;
        			}
        			
        			half4 frag (v2f i) : COLOR
        			{
        				return texCUBE(_CubeDay,i.norm); 
        			}
        			ENDCG
        		}
        	} 
        	FallBack "Diffuse"
        }

However, there is a limitation to this technique: when using a reflective water shader, you won’t get the skybox in the reflection.

This is because the reflection shader+script create a “reflection” camera by copying the main camera parameters. As the camera doesn’t use any skybox (at least any Unity skybox), the reflection camera has no skybox either.
If you want a reflected skybox in your water, you need to apply the same trick to the “reflection camera”… and probably invert the Y axis of the normal in the shader in order to have a proper reflection of the skybox.

Hope this helps!

Peace :slight_smile:

PS1: Ho! And by the way, I have a newer version of Unity now and I couldn’t reproduce all the “bugs/strange behaviours” I talked about in my first question.

PS2: For now, I accept my own answer as “THE” answer, but if anyone has a better solution, I’ll be glad to hear about it!

My bet is that your fist shader is missing a few important items:

  • Tags {“RenderType”=“Transparent” } //needed for camera depth-testing.
  • ZWrite Off //make sure not to write to the depth buffer. Else pixels behind will be occluded.

Let me know how it works!

Hi everyone, I’m writing an outline shader and I ran into the same problem. I read your answers - I quickly found a solution, I hope everyone will see it.

The whole problem is in the standard unity skybox rendering queue.
All you need to do is change your camera Clear Flags from Skybox to Depth Only and set the Depth field to 1.
Then create a second camera, configure it so that it renders only the Skybox and set the Depth value to 0 (the main thing is that it is less than the main camera.

Now one camera will always display the standard skybox, and the other will display everything else. I hope I described the solution clearly. Good luck!