Cutting a Window in a Wall with a Shader

The past solutions to this problem don’t seem to be working for me now.
I tried importing the old boat shader from the wiki, and that didn’t work. These shaders are from that wiki.
Also, the Hollowed Mountain solution doesn’t seem to work anymore either. I haven’t downloaded it and tried it since 2.6, but people posting to that thread are saying its not working any more.

My walls are plain geometry with a plain default diffuse shader.
I put this shader for a material for a plane in front of the wall, or it should work inside the wall or behind the wall also I think:

Shader "Masked/Mask" {
   
    SubShader {
        // Render the mask after regular geometry, but before masked geometry and
        // transparent things.
       
        Tags {"Queue" = "Geometry+10" }
       
        // Turn off lighting, because it's expensive and the thing is supposed to be
        // invisible anyway.
       
        Lighting Off

        // Draw into the depth buffer in the usual way.  This is probably the default,
        // but it doesn't hurt to be explicit.

        ZTest LEqual
        ZWrite On

        // Don't draw anything into the RGBA channels. This is an undocumented
        // argument to ColorMask which lets us avoid writing to anything except
        // the depth buffer.

        ColorMask 0

        // Do nothing specific in the pass:

        Pass {}
    }
}

And I put this shader on the window itself :

Shader "Masked/Diffuse Masked" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        // This shader does the same thing as the Diffuse shader, but after masks
        // and before transparent things
        Tags {"Queue" = "Geometry+20" }
        UsePass "Diffuse/BASE"
        UsePass "Diffuse/PPL"
    }
    FallBack "Diffuse", 1
}

and nothing happens. What am I doing wrong? Or, does this not work in Unity 3?

Sincerely,
Looking For A Solution in Austin

UsePass works perfectly well in Unity3.

Not sure why it’s not working, though.

It could be that the Diffuse/BASE Diffuse/PPL passes have their own Queue setting? It’d override the one you define in the SubShader.

Thank you both for your replies. I’m still stuck here.

Do you have a workaround that might help me?

Meh11: I put that shader on a cube by itself to simplify things and it still appears as a normal diffuse, appearing in front / behind objects as it normally would in space. Any more ideas?

Thanks guys, still struggling here.

You can’t use a surface shader as a pass, no.

But anything you write yourself in passes, can be referenced in a UsePass. I’ve got an entire game running off one shader file that contains the passes and the shaders I use just UsePass-ing the relevant passes I need.

Can you open the Diffuse shader up and check what it’s Queue settings are? Just to be sure it’s not that.

Also, if you’re referencing the built-in diffuse shader (rather than your own replacement) for UsePass… it won’t work. It doesn’t have named passes as it’s a surface shader. So Meh11’s correct that it’s likely falling back to the regular Diffuse shader.

Try putting this in a shader file and applying this to your mesh (it’s the Diffuse shader, just with Geometry+20 Queue)…

Shader "Diffuse Geo+20" {
Properties {
	_Color ("Main Color", Color) = (1,1,1,1)
	_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
	Tags { "RenderType"="Opaque" "Queue" = "Geometry+20"}
	LOD 200

CGPROGRAM
#pragma surface surf Lambert

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.rgb;
	o.Alpha = c.a;
}
ENDCG
}

Fallback "VertexLit"
}

Now it is pink without the fallback command. It wasn’t before I put in that latest shader.

I’ve gotten so good at programming since I’ve been using Unity. Lots of JS, switched to C#, object oriented, passing classes back and forth, organizing all the code, doing great. I can’t figure out why it’s so hard for me to learn shaders. Shouldn’t I be able to take one single shader and change the Queue tag and have this work?

Okay now this is interesting. I just noticed on this shader I get an error “! No subshaders can run on this graphics card.” Just to make sure I updated my drivers today, it’s a Nvidia geforce 9800 gt.

Shader "Masked/Diffuse Masked" 
{
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        // This shader does the same thing as the Diffuse shader, but after masks
        // and before transparent things
        Tags {"Queue" = "Geometry+20" }
        UsePass "Diffuse/BASE"
        UsePass "Diffuse/PPL"
    }
}

confused.
the error goes away when I put a fallback in there.

Oh wait, here we go… Farfarer’s last script is see-through. Now I’m going somewhere.

Thanks guys, I might be able to crack it. I’ll let you know either way.

Great. You guys helped me do it. Thank you both so much.

Final shaders: for the window mask:

Shader "Masked/Mask" {

	Properties {
		_Color ("Main Color", Color) = (0,0,0,0)
	}
	
    SubShader {
        // Render the mask after regular geometry, but before masked geometry and
        // transparent things.
       
        Tags {"Queue" = "Geometry+10" }
       
        // Turn off lighting, because it's expensive and the thing is supposed to be
        // invisible anyway.
       
        Lighting Off

        // Draw into the depth buffer in the usual way.  This is probably the default,
        // but it doesn't hurt to be explicit.

        ZTest LEqual
        ZWrite On

        // Don't draw anything into the RGBA channels. This is an undocumented
        // argument to ColorMask which lets us avoid writing to anything except
        // the depth buffer.

        ColorMask 0

        // Do nothing specific in the pass:

        Pass {}
    }
}

for the window:

Shader "Masked/Diffuse Masked" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        // This shader does the same thing as the Diffuse shader, but after masks
        // and before transparent things
        Tags {"Queue" = "Geometry+20" }
        UsePass "Diffuse/BASE"
        UsePass "Diffuse/PPL"
    }
    FallBack "Diffuse", 1
}

for the wall:

Shader "Diffuse Geo+20" {
Properties {
	_Color ("Main Color", Color) = (1,1,1,1)
	_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
	Tags { "RenderType"="Opaque" "Queue" = "Geometry+20"}
	LOD 200

CGPROGRAM
#pragma surface surf Lambert

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.rgb;
	o.Alpha = c.a;
}
ENDCG
}

Fallback "VertexLit"
}

Once again, hugs and kisses all around!
Pour everyone a glass of water! It’s on me!

Friends,

I’m having a little trouble with the way the Mask renders with the skybox. It doesn’t render where the sky box is. You can see in the attached image a doorway on the right, which is regular geometry, and the door on the left which uses our mask. Through the mask the terrain renders normally, but the skybox isn’t showing up.

Any ideas on how to have the skybox render behind all geometry except the mask?

Thanks.

Now how to write that code in C#. I tried this in a script attached to the main camera, and it compiled:

void Start()
{
			// set the render queue of the skybox:
		Skybox mySky = gameObject.camera.GetComponent<Skybox>();
		print(mySky);
		mySky.material.renderQueue = 9;
}

It doesn’t throw any errors, but no matter what number I put in there, the problem persists.

Any more ideas?

I found the skybox shader, and am wondering what to do to adjust it to be visible through the mask shader above. Here’s the shader. of course it’s pretty long, but the answer should be something like changing the top to change the queue to Geometry+9 (tried, didn’t work by itself, nor other numbers), and change the ‘Render Type’ from background?

Sorry I need so much hand-holding for this process. At least this will be valuable for people who want to drop windows and doors in their buildings and such.

Any suggestions are appreciated.
Thanks.

Shader "RenderFX/Skybox" {
Properties {
	_Tint ("Tint Color", Color) = (.5, .5, .5, .5)
	_FrontTex ("Front (+Z)", 2D) = "white" {}
	_BackTex ("Back (-Z)", 2D) = "white" {}
	_LeftTex ("Left (+X)", 2D) = "white" {}
	_RightTex ("Right (-X)", 2D) = "white" {}
	_UpTex ("Up (+Y)", 2D) = "white" {}
	_DownTex ("down (-Y)", 2D) = "white" {}
}

SubShader {
	Tags { "Queue"="Background" "RenderType"="Background" }
	Cull Off ZWrite Off Fog { Mode Off }
	
	CGINCLUDE
	#include "UnityCG.cginc"

	fixed4 _Tint;
	
	struct appdata_t {
		float4 vertex : POSITION;
		float2 texcoord : TEXCOORD0;
	};
	struct v2f {
		float4 vertex : POSITION;
		float2 texcoord : TEXCOORD0;
	};
	v2f vert (appdata_t v)
	{
		v2f o;
		o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
		o.texcoord = v.texcoord;
		return o;
	}
	fixed4 skybox_frag (v2f i, sampler2D smp)
	{
		fixed4 tex = tex2D (smp, i.texcoord);
		fixed4 col;
		col.rgb = tex.rgb + _Tint.rgb - 0.5;
		col.a = tex.a * _Tint.a;
		return col;
	}
	ENDCG
	
	Pass {
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest
		sampler2D _FrontTex;
		fixed4 frag (v2f i) : COLOR { return skybox_frag(i,_FrontTex); }
		ENDCG 
	}
	Pass{
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest
		sampler2D _BackTex;
		fixed4 frag (v2f i) : COLOR { return skybox_frag(i,_BackTex); }
		ENDCG 
	}
	Pass{
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest
		sampler2D _LeftTex;
		fixed4 frag (v2f i) : COLOR { return skybox_frag(i,_LeftTex); }
		ENDCG
	}
	Pass{
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest
		sampler2D _RightTex;
		fixed4 frag (v2f i) : COLOR { return skybox_frag(i,_RightTex); }
		ENDCG
	}	
	Pass{
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest
		sampler2D _UpTex;
		fixed4 frag (v2f i) : COLOR { return skybox_frag(i,_UpTex); }
		ENDCG
	}	
	Pass{
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest
		sampler2D _DownTex;
		fixed4 frag (v2f i) : COLOR { return skybox_frag(i,_DownTex); }
		ENDCG
	}
}	

SubShader {
	Tags { "Queue"="Background" "RenderType"="Background" }
	Cull Off ZWrite Off Fog { Mode Off }
	Color [_Tint]
	Pass {
		SetTexture [_FrontTex] { combine texture +- primary, texture * primary }
	}
	Pass {
		SetTexture [_BackTex]  { combine texture +- primary, texture * primary }
	}
	Pass {
		SetTexture [_LeftTex]  { combine texture +- primary, texture * primary }
	}
	Pass {
		SetTexture [_RightTex] { combine texture +- primary, texture * primary }
	}
	Pass {
		SetTexture [_UpTex]    { combine texture +- primary, texture * primary }
	}
	Pass {
	SetTexture [_DownTex]  { combine texture +- primary, texture * primary }	}
}
}

Did you solve this problem ?