- Home /
How do I make a multipass shader that uses different queues?
So I've been trying to make a shader where the self-illuminated parts of the material render after blob shadow projectors (so that shadows don't darken lights, as one would expect), so I wrote a multipass shader and tried to make the two passes have different queue tags so they would render before and after the shadow projector shader (which has a queue of "Transparent-2")
However the queue thing doesn't seem to work - the two passes seem to always render in the same queue despite the two different tag declarations (meaning either both passes cover the blob shadow or both passes are shadowed). Aside from that, the shaders behave right (i.e. both passes are running and behaving as desired), I'm just not getting the blob shadow to show up right.
Here's the shader code:
Shader "Custom/Bump Reflect Illum" {
Properties {
_Color ("Main Color", Color) = (0.5,0.5,0.5,1)
_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
_BumpMap ("Normalmap", 2D) = "bump" {}
_Cube ("Reflection Cubemap", Cube) = "_Skybox" { TexGen CubeReflect }
_ReflectColor ("Reflection Color", Color) = (0.5,0.5,0.5,1)
_IllumColor ("Illum Color", Color) = (.5, 0.5, 0.5, 1)
_Illum ("Illumin (A)", 2D) = "black" {}
_IllumExponent ("Illumination Directionality", Range(0.0, 6)) = 2.0
_BlowoutFactor ("Blowout to White", Range(0.0, 3)) = .3
}
SubShader
{
Tags { "RenderType"="Opaque" "IgnoreProjector"="False" "Queue"="Geometry"}
Name "Preshadow"
LOD 400
ZWrite On
Blend Off
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
sampler2D _BumpMap;
samplerCUBE _Cube;
fixed4 _Color;
fixed4 _ReflectColor;
struct Input {
float2 uv_MainTex;
float3 worldRefl;
INTERNAL_DATA
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
fixed4 c = tex * _Color * 2.0;
o.Albedo = c.rgb;
o.Alpha = c.a;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
float3 worldRefl = WorldReflectionVector (IN, o.Normal);
fixed4 reflcol = texCUBE(_Cube, worldRefl);
o.Emission = _ReflectColor.rgb * reflcol.rgb * c.a;
}
ENDCG
Tags { "RenderType"="Additive" "Queue"="Transparent-1" "LightMode" = "Always" }
Pass
{
Name "Self Illum"
LOD 400
ZWrite Off
ZTest LEqual
Blend One One
CGPROGRAM
// Upgrade NOTE: excluded shader from Xbox360; has structs without semantics (struct v2f members viewDir)
#pragma exclude_renderers xbox360
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD1;
float3 viewDir;
};
v2f vert (appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
TANGENT_SPACE_ROTATION;
o.viewDir = normalize(mul(rotation, normalize(ObjSpaceViewDir(v.vertex))));
return o;
}
sampler2D _BumpMap;
sampler2D _Illum;
fixed4 _IllumColor;
half _IllumExponent;
half _BlowoutFactor;
half4 frag( v2f i ) : COLOR
{
float3 normal = UnpackNormal(tex2D(_BumpMap, i.uv));
half viewNormalParallelism = saturate(dot(normalize(i.viewDir), normal));
fixed3 illum = _IllumColor.rgb * tex2D(_Illum, i.uv).rgb * pow(viewNormalParallelism, _IllumExponent) * 5.0;
fixed blowout = max(illum.r - 1.0f, 0.0f) + max(illum.g - 1.0f, 0.0f) + max(illum.b - 1.0f, 0.0f);
return half4(illum + blowout*_BlowoutFactor, 0);
}
ENDCG
}
}
Fallback "Transparent/VertexLit"
}
thanks!
Why can't you just do "IgnoreProjector"="true" in the second pass?
I can do "IgnoreProjector"="True" in the second pass - unfortunately that makes no difference at all. However if I change the first pass to "IgnoreProjector"="True", neither pass gets shadowed by the projector. Basically the two passes always behave the same way with respect to the projector for all things I've tried :(
Playing with this more, it looks like I can't change the tags at all - one subshader can only have one set of tags, and it seems that the first one reached wins :( So does anybody have any technique to make the self-illu$$anonymous$$ated part of a shader not shadowed by blob projectors? Is there a way to have multiple materials that render on the same parts of a mesh? (so I'd have two shaders ins$$anonymous$$d of one)
Sure, you can just attach two or more materials, but there are some pitfalls:
If your mesh contains submeshes, each submech will use a seperate material, if you use more material then submeshes the additional materials are only applied to the last submesh.
it your mesh consists only of one submesh, all materials are used on the mesh.
$$anonymous$$eep in $$anonymous$$d that the object is drawn multiple times when using multiple materials.
Answer by mysteryDate · Feb 03, 2015 at 11:20 PM
The reason the code above doesn't work is that "tags" apply only to subshaders, whereas culling/depth testing options apply to passes. This is not made entirely obvious in the Unity documentation (it's taken me most of the day to figure this out). Whereas you can have multiple passes in one shader, Shaderlab will pick the first compatible subshader, apply that and move on.
My guess would be that the only way to have multiple passes with different queues and rendertypes would be multiple materials, which is obviously not ideal.
Curious what queue is used for this fixed pipeline example: https://docs.unity3d.com/$$anonymous$$anual/SL-AlphaTest.html Shader "Vegetation"
Your answer
Follow this Question
Related Questions
How to change when a halo is drawn? 0 Answers
Reuse Shader Pass output as input for next Pass 0 Answers
Custom Render Queue 0 Answers
Exit out of multipass shader 0 Answers
how to do a simple multi-pass rendering? 2 Answers