bTube – 2D Texture Shader

Before I start, I must say that I know nothing about shaders at all and I managed to get this together googling & asking my friends all the way. So I’m hardly a reliable source on this topic but still thought it’s worth sharing so here we go…

If you played bTube, you must have noticed that something looks off with the incoming barriers. I mean can you even tell if they are 2D or 3D? Have a quick look if you want; bTube.

As you can see, those 2D looking slices are actually just 3D objects with a special shader that fixed their textures to 2D world. Well why did I made it in 3D then? That’s a whole another question and I can shortly say it felt easier at that time. And with this shader it’s quite hard to tell the difference anyway.

So what does this shader do? It applies the given texture in 2D screen coordinates instead of the 3D triangles. I know I’m quite horrible at describing things like these in words so just check this, yet another comparison image below;


Left, is the standard diffuse shader, applying texture to triangles in 3D coordinate system. Right is the shader I used, which doesn’t even take vertex positions into calculation, just slaps the given texture on the screen as a 2D image with no depth.

So it’s an extremely cheap & easy trick but I still believe it’s quite underused and can generate awesome effects ( as seen in bTube! ). You can find a simpler version of what I used in game below. Only difference is I used a color as multiplier for the “space effect” in bTube. Thought it was irrelevant here so took it out for this blog post.


Shader "Custom/FixedTexture" {
 Properties {
	_MainTex ("Texture", 2D) = "white" {}

SubShader {
	Tags {
	 "Queue" = "Geometry"
	LOD 100
	Pass {
		 ZWrite On  
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			sampler2D _MainTex;
			float4 _MainTex_ST;

			struct v2f {
				float4 pos : SV_POSITION;
				float4 screenPos : TEXCOORD0;
			v2f vert (appdata_base v)
				v2f o;
				o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
				o.screenPos.xyw = o.pos.xyw;
				return o;
			half4 frag (v2f i) : COLOR
				float2 screenUV = i.screenPos.xy / i.screenPos.w;
				screenUV *= _MainTex_ST.xy;
				half4 texcol = tex2D (_MainTex, screenUV);
				return texcol;


FixedTexture.shader (849.00 bytes)

Please do let me know if you have any questions!

Leave a Reply