I have two shaders, UnlitRGBA and TransparentNoOverlap. They are as follows:
UnlitRGBA.shaderlab
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
// modified by rbjacob101
Shader "Particles/Standard Unlit (RGBA)"
{
Properties
{
_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_BumpScale("Scale", Float) = 1.0
_BumpMap("Normal Map", 2D) = "bump" {}
_EmissionColor("Color", Color) = (0,0,0)
_EmissionMap("Emission", 2D) = "white" {}
_DistortionStrength("Strength", Float) = 1.0
_DistortionBlend("Blend", Range(0.0, 1.0)) = 0.5
_SoftParticlesNearFadeDistance("Soft Particles Near Fade", Float) = 0.0
_SoftParticlesFarFadeDistance("Soft Particles Far Fade", Float) = 1.0
_CameraNearFadeDistance("Camera Near Fade", Float) = 1.0
_CameraFarFadeDistance("Camera Far Fade", Float) = 2.0
// Hidden properties
[HideInInspector] _Mode("__mode", Float) = 0.0
[HideInInspector] _ColorMode("__colormode", Float) = 0.0
[HideInInspector] _FlipbookMode("__flipbookmode", Float) = 0.0
[HideInInspector] _LightingEnabled("__lightingenabled", Float) = 0.0
[HideInInspector] _DistortionEnabled("__distortionenabled", Float) = 0.0
[HideInInspector] _EmissionEnabled("__emissionenabled", Float) = 0.0
[HideInInspector] _BlendOp("__blendop", Float) = 0.0
[HideInInspector] _SrcBlend("__src", Float) = 1.0
[HideInInspector] _DstBlend("__dst", Float) = 0.0
[HideInInspector] _ZWrite("__zw", Float) = 1.0
[HideInInspector] _Cull("__cull", Float) = 2.0
[HideInInspector] _SoftParticlesEnabled("__softparticlesenabled", Float) = 0.0
[HideInInspector] _CameraFadingEnabled("__camerafadingenabled", Float) = 0.0
[HideInInspector] _SoftParticleFadeParams("__softparticlefadeparams", Vector) = (0,0,0,0)
[HideInInspector] _CameraFadeParams("__camerafadeparams", Vector) = (0,0,0,0)
[HideInInspector] _ColorAddSubDiff("__coloraddsubdiff", Vector) = (0,0,0,0)
[HideInInspector] _DistortionStrengthScaled("__distortionstrengthscaled", Float) = 0.0
}
Category
{
SubShader
{
Tags{ "RenderType" = "Opaque" "IgnoreProjector" = "True" "PreviewType" = "Plane" "PerformanceChecks" = "False" }
BlendOp[_BlendOp]
Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
Offset -1, -1
Cull[_Cull]
ColorMask RGBA
GrabPass
{
Tags{ "LightMode" = "Always" }
"_GrabTexture"
}
Pass
{
Name "ShadowCaster"
Tags{ "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma target 2.5
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
#pragma shader_feature _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON
#pragma shader_feature _REQUIRE_UV2
#pragma multi_compile_shadowcaster
#pragma multi_compile_instancing
#pragma instancing_options procedural:vertInstancingSetup
#pragma vertex vertParticleShadowCaster
#pragma fragment fragParticleShadowCaster
#include "UnityStandardParticleShadow.cginc"
ENDCG
}
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma multi_compile __ SOFTPARTICLES_ON
#pragma multi_compile_fog
#pragma target 2.5
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
#pragma shader_feature _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON
#pragma shader_feature _NORMALMAP
#pragma shader_feature _EMISSION
#pragma shader_feature _FADING_ON
#pragma shader_feature _REQUIRE_UV2
#pragma shader_feature EFFECT_BUMP
#pragma vertex vertParticleUnlit
#pragma fragment fragParticleUnlit
#pragma multi_compile_instancing
#pragma instancing_options procedural:vertInstancingSetup
#include "UnityStandardParticles.cginc"
ENDCG
}
}
}
Fallback "VertexLit"
CustomEditor "StandardParticlesShaderGUI"
}
TransparentNoOverlap.shader
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
/*
* Taken from:
* https://forum.unity.com/threads/transparent-depth-shader-good-for-ghosts.149511/
*/
Shader "Transparent/TransparentNoOverlap" {
Properties {
[PerRendererData]_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
}
SubShader {
Tags {"RenderType"="Transparent" "Queue"="Transparent" "IgnoreProjector"="True"}
LOD 200
Pass {
Name "TRANSPARENT"
ZWrite On
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGBA
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed4 _Color;
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos (v.vertex);
return o;
}
half4 frag (v2f i) : COLOR
{
return _Color;
}
ENDCG
}
CGPROGRAM
#pragma surface surf Lambert alpha
#pragma debug
sampler2D _MainTex;
fixed4 _Color;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgba;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Transparent/Diffuse"
}
I want materials using UnlitRGBA to always render over TransparentNoOverlap. What would I do in order to achieve this result? I have tried adding Offset -1, -1
or Offset 0, -1
to UnlitRGBA. When testing this against the standard surface shader, it works fine and the UnlitRGBA consistently renders on top. But when rendering with TransparentNoOverlap, either there is z-fighting or TransparentNoOverlap always renders on top. Why is this? I think that perhaps it has something to do with ZTests or ZWrites, but I am ultimately unsure.
I apologize for the large code samples... Thanks for any help you can provide.
rbjacob
Note that the expected result and the setup are slightly ambiguous, so there might be several ways to go.
Simply put: Material with shader A (Unlit) is covered up by B (Transparent) because B is drawn after it. "Queue"="Transparent" is the flag responsible for that effect in B. Shader A doesn't have it so it uses the default "Geometry" queue. (You can read about the index value used under the hood here: https://docs.unity3d.com/Manual/SL-SubShaderTags.html). So in this regard you could specify the queue indices explicitly, and make sure they match your expected behavior.
This disregards another aspect: the ZBuffer, which deals with occlusion of one mesh by another, made so that they are actually not dependent on that draw order. Pixels can be discarded based on a depth test, and depth can be written by object if specified to do so. (https://docs.unity3d.com/Manual/SL-CullAndDepth.html)
Meshes display z-fighting if both of them write and test, and are co-planar (in the same spot) or the buffer has low precision so the values stored make it seems like they are.
Provided that both your meshes need to be occluded and occlude others and themselves, one way would be to set B (Transparent) to use ZTest Less, so that it only appears when A is not present at all, even if drawn after A, and even if co-planar with A.