Is there a way to reliably enable and disable a shader pass in a multi-pass shader?
I can’t seem to find a way to do that without experimenting with a bunch of hacks (or I’ve missed the documented method which could likely be the case ).
thanks…
Is there a way to reliably enable and disable a shader pass in a multi-pass shader?
I can’t seem to find a way to do that without experimenting with a bunch of hacks (or I’ve missed the documented method which could likely be the case ).
thanks…
No. Please try creating a text file with a bunch of UsePass lines, and let us know if you can create a material from that. I never tried. If it works, I’d use that method. Otherwise, I’d keep a bunch of shaders around that contain the UsePass lines you want.
5 years later, I’ve run into the same question… Is there a way to enable/disable a shader pass per-material at runtime?
I’ve got a shader with a lot of variants, and I’d like to add some VFX to the shader.
Rather than doubling the (already concerning) number of shader variants by adding new #pragma multi_compiles, I could apply some of these effects with a second pass - but only if I can turn it on/off as needed. Is there any way to do this?
Solution 1:
Use Material.SetPass
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MultiPass : MonoBehaviour
{
public RenderTexture Source;
public RenderTexture Destination;
public Material material;
public int pass;
void Blit(RenderTexture source, RenderTexture destination, Material mat)
{
RenderTexture.active = destination;
mat.SetTexture("_MainTex", source);
GL.PushMatrix();
GL.LoadOrtho();
GL.invertCulling = true;
mat.SetPass(0);
GL.Begin(GL.QUADS);
GL.MultiTexCoord2(0, 0.0f, 0.0f);
GL.Vertex3(0.0f, 0.0f, 0.0f);
GL.MultiTexCoord2(0, 1.0f, 0.0f);
GL.Vertex3(1.0f, 0.0f, 0.0f);
GL.MultiTexCoord2(0, 1.0f, 1.0f);
GL.Vertex3(1.0f, 1.0f, 1.0f);
GL.MultiTexCoord2(0, 0.0f, 1.0f);
GL.Vertex3(0.0f, 1.0f, 0.0f);
GL.End();
GL.invertCulling = false;
GL.PopMatrix();
}
void Start ()
{
}
void Update ()
{
Blit(Source,Destination,material);
}
}
Shader "MultiPass"
{
SubShader
{
CGINCLUDE
#pragma vertex SetVertexShader
#pragma fragment SetPixelShader
void SetVertexShader (inout float4 vertex:POSITION,inout float2 uv:TEXCOORD0)
{
vertex = UnityObjectToClipPos(vertex);
}
ENDCG
Pass
{
CGPROGRAM
float4 SetPixelShader (float4 vertex:POSITION,float2 uv:TEXCOORD0) : SV_TARGET
{
return float4(1,0,0,1);
}
ENDCG
}
Pass
{
CGPROGRAM
float4 SetPixelShader (float4 vertex:POSITION,float2 uv:TEXCOORD0) : SV_TARGET
{
return float4(0,0,1,1);
}
ENDCG
}
}
}
Shader output (second pass):
Render texture with first pass:
so you can combine Blit with various passes.
Solution 2:
Use discard and Material.SetFloat:
Shader "MultiPass"
{
SubShader
{
CGINCLUDE
#pragma vertex SetVertexShader
#pragma fragment SetPixelShader
void SetVertexShader (inout float4 vertex:POSITION,inout float2 uv:TEXCOORD0)
{
vertex = UnityObjectToClipPos(vertex);
}
ENDCG
Pass
{
CGPROGRAM
float4 SetPixelShader (float4 vertex:POSITION,float2 uv:TEXCOORD0) : SV_TARGET
{
return float4(1,0,0,1);
}
ENDCG
}
Pass
{
CGPROGRAM
float4 SetPixelShader (float4 vertex:POSITION,float2 uv:TEXCOORD0) : SV_TARGET
{
if (true)
{
discard;
}
return float4(0,0,1,1);
}
ENDCG
}
}
}
Shader output:
Solution 3:
Write custom native rendering plugin with multipass support. For OpenGL here is topic about compact code:
https://forum.unity.com/threads/unity-opengl-native-plugin-basic-source-code.570571/
Solution 4:
Play with various blending modes, to “hide” output of given pass:
Solution 5:
Use stencil buffer: