Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Transparency issues in 4.5

Discussion in 'Shaders' started by emmalloyd, Jul 9, 2014.

  1. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Hey guys, sorry for the double post, I wasn't sure where best to put this:

    I've been having some issues with transparency after the 4.5 update. I've created a 2D water shader, which has an alpha mask tiled along the top to give a wave effect. As well as that the alpha of the whole material is changeable so that objects behind it can be seen.

    The issue I'm having is that the transparency seems to randomly break. It stops rendering things behind the object that it is applied to altogether. At first, it all worked fine. And then for no apparent reason, it stops. It also sometimes stops working when I reopen unity. Am I making some really nooby mistake here or are other people having this issue?

    Working.png
    This is what it looks like working (please excuse the poor image quality).

    And Below is what it looks like broken.
    Broken.png
    To get the working image I had to create a new shader, but the foreground water in both images has exactly the same code in them, the only difference is the name.

    Edit: Here is the shader code:
    Code (CSharp):
    1. Shader "Custom/NewWater" {
    2.     Properties
    3.     {
    4.         _Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
    5.         _MainTex ("Main Texture", 2D) = "White" {}
    6.         _AlphaMask ("Alpha Mask", 2D) = "White" {}
    7.         _BubbleSpeed ("Bubble Speed", Float) = 1
    8.         _AnimSpeed ("Animation Speed", Float) = 1.0
    9.         _SetAlpha ("Set Alpha", Float) = 1.0
    10.     }
    11.  
    12.     SubShader
    13.     {
    14.         Pass
    15.         {
    16.             Tags {"Queue" = "Transparent"}
    17.             Blend SrcAlpha OneMinusSrcAlpha
    18.        
    19.             Lighting Off
    20.        
    21.             CGPROGRAM
    22.             #pragma vertex vert
    23.             #pragma fragment frag
    24.        
    25.             uniform float4 _Color;
    26.             uniform sampler2D _MainTex;
    27.             uniform float4 _MainTex_ST;
    28.             uniform sampler2D _AlphaMask;
    29.             uniform float4 _AlphaMask_ST;
    30.             uniform float _BubbleSpeed;
    31.             uniform float _AnimSpeed;
    32.             uniform float _SetAlpha;
    33.        
    34.             struct vertexInput
    35.             {
    36.                 float4 vertex : POSITION;
    37.                 float4 texcoord : TEXCOORD0;
    38.             };
    39.        
    40.             struct vertexOutput
    41.             {
    42.                 float4 pos : SV_POSITION;
    43.                 float4 tex : TEXCOORD0;
    44.                 float4 uvPos : TEXCOORD1;
    45.             };
    46.        
    47.             vertexOutput vert (vertexInput input)
    48.             {
    49.                 vertexOutput output;
    50.            
    51.                 output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
    52.                 output.tex = input.texcoord;
    53.                 output.uvPos = input.texcoord;
    54.            
    55.                 return output;
    56.             }
    57.        
    58.             float4 frag (vertexOutput input) : COLOR
    59.             {
    60.            
    61.                 float4 tex = tex2D(_MainTex, input.tex.xy * _MainTex_ST.xy + float2(_MainTex_ST.z / _MainTex_ST.x , _MainTex_ST.w / _MainTex_ST.y ) * _Time * _BubbleSpeed);
    62.                 float4 mask = tex2D(_AlphaMask, input.tex.xy * _AlphaMask_ST.xy + (_AlphaMask_ST.zw * _Time * _AnimSpeed));
    63.                 float alpha = 1 - mask.a;
    64.                 float4 finalColor;
    65.                 float finalAlpha;
    66.            
    67.                 if ( input.tex.y < 1 - ( 1 / _AlphaMask_ST.y ) )
    68.                 {
    69.                     finalAlpha = 1 * _SetAlpha;
    70.                 } else {
    71.                     finalAlpha = _SetAlpha * alpha;
    72.                 }
    73.                            
    74.                 finalColor = float4(_Color.rgb * (1 - tex.a), 1.0);
    75.                 float4 finalTex = float4(tex.rgb * tex.a, 1.0);            
    76.            
    77.                 return float4(finalColor.rgb + finalTex.rgb, finalAlpha);
    78.             }
    79.        
    80.             ENDCG
    81.         }
    82.     }
    83. }
    Any help with this would be greatly appreciated!
     
  2. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Looks like standard alpha sorting issues.

    You probaly want to turn off ZWrite so that it doesn't write to the ZBuffer (transparent shaders generally shouldn't). That'll stop it completey hiding the layer behind it.

    And if you must have the two planes sort properly, you'll have to ensure that the one you want in front is physically in front of the back plane.
    Or you could write two shaders, one with a Queue of Transparent and one of Transparent+1, giving the +1 shader to the front plane's material. That will force it to be drawn after the back plane.
     
    emmalloyd likes this.
  3. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Thanks, I completely forgot about Zwrite! That has fixed the transparency part. But now it renders my foreground behind my background, I've tried adding +1 to the foreground shader, and my gameobjects are on separate layers, and the front water is definitely closer on the z axis than the background water. Thank you so much for your help!
     
  4. Mike-Geig

    Mike-Geig

    Unity Technologies

    Joined:
    Aug 16, 2013
    Posts:
    220
    Can we see the new version of your shader?
     
  5. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Background water:
    Code (CSharp):
    1. Shader "Custom/BackgroundWater" {
    2.     Properties
    3.     {
    4.         _Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
    5.         _MainTex ("Main Texture", 2D) = "White" {}
    6.         _AlphaMask ("Alpha Mask", 2D) = "White" {}
    7.         _BubbleSpeed ("Bubble Speed", Float) = 1
    8.         _AnimSpeed ("Animation Speed", Float) = 1.0
    9.         _SetAlpha ("Set Alpha", Float) = 1.0
    10.     }
    11.  
    12.     SubShader
    13.     {
    14.         Pass
    15.         {  
    16.             Tags {"Queue" = "Transparent +1"}
    17.             Blend SrcAlpha OneMinusSrcAlpha
    18.          
    19.             Lighting Off
    20.             Zwrite Off
    21.          
    22.             CGPROGRAM
    23.             #pragma vertex vert
    24.             #pragma fragment frag
    25.          
    26.             uniform float4 _Color;
    27.             uniform sampler2D _MainTex;
    28.             uniform float4 _MainTex_ST;
    29.             uniform sampler2D _AlphaMask;
    30.             uniform float4 _AlphaMask_ST;
    31.             uniform float _BubbleSpeed;
    32.             uniform float _AnimSpeed;
    33.             uniform float _SetAlpha;
    34.          
    35.             struct vertexInput
    36.             {
    37.                 float4 vertex : POSITION;
    38.                 float4 texcoord : TEXCOORD0;
    39.             };
    40.          
    41.             struct vertexOutput
    42.             {
    43.                 float4 pos : SV_POSITION;
    44.                 float4 tex : TEXCOORD0;
    45.                 float4 uvPos : TEXCOORD1;
    46.             };
    47.          
    48.             vertexOutput vert (vertexInput input)
    49.             {
    50.                 vertexOutput output;
    51.              
    52.                 output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
    53.                 output.tex = input.texcoord;
    54.                 output.uvPos = input.texcoord;
    55.              
    56.                 return output;
    57.             }
    58.          
    59.             float4 frag (vertexOutput input) : COLOR
    60.             {
    61.              
    62.                 float4 tex = tex2D(_MainTex, input.tex.xy * _MainTex_ST.xy + float2(_MainTex_ST.z / _MainTex_ST.x , _MainTex_ST.w / _MainTex_ST.y ) * _Time * _BubbleSpeed);
    63.                 float4 mask = tex2D(_AlphaMask, input.tex.xy * _AlphaMask_ST.xy + (_AlphaMask_ST.zw * _Time * _AnimSpeed));
    64.                 float alpha = 1 - mask.a;
    65.                 float4 finalColor;
    66.                 float finalAlpha;
    67.              
    68.                 if ( input.tex.y < 1 - ( 1 / _AlphaMask_ST.y ) )
    69.                 {
    70.                     finalAlpha = 1 * _SetAlpha;
    71.                 } else {
    72.                     finalAlpha = _SetAlpha * alpha;
    73.                 }
    74.                              
    75.                 finalColor = float4(_Color.rgb * (1 - tex.a), 1.0);
    76.                 float4 finalTex = float4(tex.rgb * tex.a, 1.0);              
    77.              
    78.                 return float4(finalColor.rgb + finalTex.rgb, finalAlpha);
    79.             }
    80.          
    81.             ENDCG
    82.         }
    83.     }
    84. }
    Foreground water:
    Code (CSharp):
    1. Shader "Custom/ForegroundWater" {
    2.     Properties
    3.     {
    4.         _Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
    5.         _MainTex ("Main Texture", 2D) = "White" {}
    6.         _AlphaMask ("Alpha Mask", 2D) = "White" {}
    7.         _BubbleSpeed ("Bubble Speed", Float) = 1
    8.         _AnimSpeed ("Animation Speed", Float) = 1.0
    9.         _SetAlpha ("Set Alpha", Float) = 1.0
    10.     }
    11.  
    12.     SubShader
    13.     {
    14.         Pass
    15.         {  
    16.             Tags {"Queue" = "Transparent"}
    17.             Blend SrcAlpha OneMinusSrcAlpha
    18.          
    19.             Lighting Off
    20.             Zwrite Off
    21.          
    22.             CGPROGRAM
    23.             #pragma vertex vert
    24.             #pragma fragment frag
    25.          
    26.             uniform float4 _Color;
    27.             uniform sampler2D _MainTex;
    28.             uniform float4 _MainTex_ST;
    29.             uniform sampler2D _AlphaMask;
    30.             uniform float4 _AlphaMask_ST;
    31.             uniform float _BubbleSpeed;
    32.             uniform float _AnimSpeed;
    33.             uniform float _SetAlpha;
    34.          
    35.             struct vertexInput
    36.             {
    37.                 float4 vertex : POSITION;
    38.                 float4 texcoord : TEXCOORD0;
    39.             };
    40.          
    41.             struct vertexOutput
    42.             {
    43.                 float4 pos : SV_POSITION;
    44.                 float4 tex : TEXCOORD0;
    45.                 float4 uvPos : TEXCOORD1;
    46.             };
    47.          
    48.             vertexOutput vert (vertexInput input)
    49.             {
    50.                 vertexOutput output;
    51.              
    52.                 output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
    53.                 output.tex = input.texcoord;
    54.                 output.uvPos = input.texcoord;
    55.              
    56.                 return output;
    57.             }
    58.          
    59.             float4 frag (vertexOutput input) : COLOR
    60.             {
    61.              
    62.                 float4 tex = tex2D(_MainTex, input.tex.xy * _MainTex_ST.xy + float2(_MainTex_ST.z / _MainTex_ST.x , _MainTex_ST.w / _MainTex_ST.y ) * _Time * _BubbleSpeed);
    63.                 float4 mask = tex2D(_AlphaMask, input.tex.xy * _AlphaMask_ST.xy + (_AlphaMask_ST.zw * _Time * _AnimSpeed));
    64.                 float alpha = 1 - mask.a;
    65.                 float4 finalColor;
    66.                 float finalAlpha;
    67.              
    68.                 if ( input.tex.y < 1 - ( 1 / _AlphaMask_ST.y ) )
    69.                 {
    70.                     finalAlpha = 1 * _SetAlpha;
    71.                 } else {
    72.                     finalAlpha = _SetAlpha * alpha;
    73.                 }
    74.                              
    75.                 finalColor = float4(_Color.rgb * (1 - tex.a), 1.0);
    76.                 float4 finalTex = float4(tex.rgb * tex.a, 1.0);              
    77.              
    78.                 return float4(finalColor.rgb + finalTex.rgb, finalAlpha);
    79.             }
    80.          
    81.             ENDCG
    82.         }
    83.     }
    84. }
     
  6. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Again it seems a bit random, sometimes it will render in the right order and sometimes it won't.
     
  7. Mike-Geig

    Mike-Geig

    Unity Technologies

    Joined:
    Aug 16, 2013
    Posts:
    220
    This seems ridiculously pedantic, but try removing the space before the +1:

    Tags { "Queue" = "Transparent+1" }

    I could just see a parser stopping when it hits a space or something (doubtful, but can't hurt to try)
     
  8. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    The foreground water should have the +1, not the background water. You want the foreground to draw after the background.

    Currently this will always draw the background before the foreground

    And yes, you'll want to remove the space between Transparent and +1.

    Higher Queue numbers are drawn after lower numbers (objects with the same number will get drawn together).
    So Transparent is higher than TransparentCutout, which is higher than Opaque (and I think, in turn, that's higher than Background).
    There are 999 numbers between each of those presets (if I recall, each of those levels translates to 4000, 3000, 2000 and 1000, respectively, so you should have a good range to play with - the exact numbers are in the documentation somewhere). You could write just a number if you prefer, too ("Queue"="4001", for example) but it's a bit easier to stick to the word for clarity's sake.
     
  9. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    :( Thank you but unfortunately not. As I said before, it seems random because at the moment (unfortunately not because of the shader adjustment) the water objects are rendering in the right order, but things that should be behind them are rendering on top.

    zdepthissue.png

    The quad just has default diffuse shader on it, so the water should render in front because it is in the transparent render queue, should it not? Thank you again!
     
  10. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Yes, sorry, I realised after that post that I had an error in there. But it isn't actually making a difference. I've tried them both with and without the +1, together and separately, but nothing seems to actually change the order that they render in.
     
  11. Mike-Geig

    Mike-Geig

    Unity Technologies

    Joined:
    Aug 16, 2013
    Posts:
    220
    Are you able to email me a copy of that project (water, object, shader, and scene) to mike@unity3d.com? I work much better when I can just play around and try things out.
     
  12. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Thanks Mike, I have sent you the project as requested, I hope my email makes sense.
     
  13. TomasJ

    TomasJ

    Joined:
    Sep 26, 2010
    Posts:
    256
    Not if you have Z test enabled.
     
  14. Mike-Geig

    Mike-Geig

    Unity Technologies

    Joined:
    Aug 16, 2013
    Posts:
    220
    Interestingly enough. I copy / pasted your code and let Unity recompile and it worked fine. As soon as I closed and reopened, it reverted back. Hmmm.

    I converted it to a surface shader and it worked just fine, but lighting became the limitation (surface shaders use lighting). An obvious hack solution would be to use surface shaders and add ambient light to the scene, but it would be less performant.
     
  15. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    If you want solve this problem by altering queues, it's probably much easier to set the render queue for each material directly via script. That way you don't need a different copy of your shader for each queue you want to use.

    This can still be a lot of work, though. Rather than messing with queues, it might be easier still to try and physically sort your layers in the order you want them to render. That is, keep all your transparent shaders in the Transparent queue, and make sure you're giving Unity enough information to sort all the layers by depth.

    First, make sure you know your transparency sorting mode. If you're using a perspective camera that doesn't rotate, you might find orthographic sorting is appropriate.

    Then all you need to do is keep in mind that objects are sorted by their origins, which might not be the centre of their bounds.

    Once you've got your stack in order with physical sorting, it's much easier to modify than if you're relying on render queues.
     
  16. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    @Mike Geig Thank you, I'm kind of glad it's not just me lol. Any further suggestions?

    @Daniel Brauer Thanks for your reply. I'm working in 2D so my camera is orthographic. Is there another way to define orthographic sorting? I also posted this in the unity support forums, someone there suggested a script to set the render queue, but this didn't seem to work either. I will try it again tomorrow and make sure it isn't just me making a silly mistake.

    Edit: Removed link to second post, because it appears to have been deleted.
    Here is the code for the script that someone provided for me:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [AddComponentMenu("Effects/SetRenderQueue")]
    5.  
    6. [RequireComponent(typeof(Renderer))]
    7.  
    8. public class SetRenderQueue : MonoBehaviour {
    9.    
    10.     public int queue = 1;
    11.     public int[] queues;
    12.    
    13.     protected void Start() {
    14.        
    15.         if (!renderer || !renderer.sharedMaterial || queues == null)
    16.             return;
    17.        
    18.         renderer.sharedMaterial.renderQueue = queue;
    19.        
    20.         for (int i = 0; i < queues.Length && i < renderer.sharedMaterials.Length; i++)
    21.            
    22.             renderer.sharedMaterials[i].renderQueue = queues[i];    
    23.     }
    24. }
    25.  
    I have tried playing with it again this morning, and I can change the order in which the water objects render, but it is still not affecting anything else in the scene, regardless of the numbers I type in the "Queue" box. I set both the waters to 4000, and the quad to 1, and the quad still renders in front :/

    Thank you again :)
     
    Last edited: Jul 10, 2014
  17. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Orthographic transparency sorting is definitely what you want with an orthographic camera, and it should be pretty easy to judge what is in front by looking at it in the scene view.

    That script should work, although because it runs in Start() it will only apply your queue values when you push Play. Material.renderQueue is a serialized value, which means that changes made by that script should persist after you stop the game again.

    Maybe this is a stupid question, but is the quad actually closer to the camera than the water? If so, queue order won't matter because it writes to the depth buffer, preventing anything behind it from being rendered in front later.
     
  18. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    I just checked, and it's possible you don't need that script at all. If you set your inspector to debug mode, you can edit the "custom queue" field directly. Changes here should take effect immediately.
     
  19. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Nope, the quad is further away. I will try the "custom queue" thing. I did have a quick look at that earlier though, on a different project, and couldn't see it. Is it still an option on sprites?
    Thank you.
     
  20. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Custom queue is a Material property, so you need to select a Material asset (with your inspector in debug mode) to see and edit it directly.
     
  21. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Oh my goodness, thank you! This worked perfectly! :)

    Thank you so much for your help everyone!
     
  22. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20
    Sorry to resurrect this again so quickly, but I have another problem. After applying a sorting layer to the character, the custom render queue thing doesn't make a difference to rendering. I assume it is to do with the sorting layers, but I can't apply a sorting layer to the water as it isn't a sprite. Any help would be great :) Thanks again.
     
  23. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    You can apply a sorting layer to any renderer, but you have to do it using a script. See the documentation for Renderer.
     
  24. emmalloyd

    emmalloyd

    Joined:
    Dec 5, 2013
    Posts:
    20