- Home /
Multipass Surface Shader (or equivalent)?
Hi all.
I'm trying to create a real two-side shader. For that, I need to render two passes: one with front faces, one with back faces and flipped normals. The problem, is that I can't define a CGPROGRAM which does surface shading in a Pass. It seems CGPROGRAM's in passes can only do vertex/fragment shading. So how would I do this? I can't think of a way to combine the two passes into one, and I also can't figure out a way to do two surface shader passes. Any help would be highly appreciated.
Answer by tanoshimi · Jan 06, 2014 at 07:45 PM
You can't explicitly define passes for surface shaders; Unity creates them automatically. But that doesn't mean you can't have multipass surface shaders - you just list the appropriate surface shader code one after another and, in the compiled output, Unity will create the corresponding passes, one after another.
For example, a material using the following surface shader renders green front faces and red back faces:
Shader "Custom/DoubleSided" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
// Render back faces first
Cull Front
CGPROGRAM
#pragma surface surf Lambert vertex:vert
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
// Flip normal for back faces
void vert (inout appdata_full v) {
v.normal *= -1;
}
// Red back faces
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = fixed3(1,0,0);
o.Alpha = c.a;
}
ENDCG
// Now render front faces
Cull Back
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
// Green front faces
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = fixed3(0,1,0);
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
Applied to a cylinder mesh with the top face removed gives:
Huh. I did not know you could do that. There are benefits to having the different faces as separate shaders (it allows you to mix and match styles - e.g. have a specular shader on one side and a normal mapped shader on the other - without having to make a shader for each combination), but this is a rather neat way to do this.
What the... I never even imagined it would work this way; actually, it's so simple that it's hurting my pride. Anyway, thanks a ton for this! $$anonymous$$eanwhile, I also found another way. You can write many shaders and combine them into one with usepass, but even that's not necessary anymore.
I'd completely forgotten about usepass. Should be worth noting that usepass is not compatible with Unity free.
why this is not included in documentation? I've looking this for hours, and came up with this one.
Answer by Hoeloe · Jan 06, 2014 at 10:57 AM
You can't. You need to use either a vertex shader or two separate shaders, and give the object two materials. I have a package on the asset store that does exactly this using the second of those methods: https://www.assetstore.unity3d.com/#/content/11351