Glass - with all the bells and whistles

My friend wants a shader which has just about all the features that a piece of glass could possibly have - transparency, the ability to distort things behind it, variable tinting, transmission of light through it, and being Beast-aware.

I have all of those plugged in, but now I’m stuck on adding another feature - fresnel cubemap reflection, which needs to be normal-aware.

My current attempt was based on taking a procedurally-generated cubemap shader (using surface shader code), and adding that to my previous shader. Unfortunately the cubemap (although it behaves well enough), overrides nearly all of the features of the existing code.

My current code is below, and I’m hoping someone can help me work out where I’ve gone wrong…

Shader "AV/Glass/AVStained BumpDistort Transparent CubeTest 001" {
Properties {
	_BumpAmt  ("Distortion", range (0,128)) = 10
	_MainTex ("Tint Color (RGB), Transparency (A)", 2D) = "white" {}
	_BumpMap ("Normalmap", 2D) = "bump" {}
	_TransparencyLM ("Transmissive Colour", 2D) = "white" {}
	_SamplerCube0("CubeMap", CUBE) = "" {}
}


	SubShader 
	{
		Tags
		{
"RenderType"="Opaque"

		}
		
		CGPROGRAM
			#pragma surface surf BlinnPhongEditor 
			
			struct EditorSurfaceOutput {
				half3 Albedo;
				half3 Normal;
				half3 Emission;
				half3 Gloss;
				half Specular;
				half Alpha;
			};
			
			inline half4 LightingBlinnPhongEditor (EditorSurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
			{
				#ifndef USING_DIRECTIONAL_LIGHT
				lightDir = normalize(lightDir);
				#endif
				viewDir = normalize(viewDir);
				half3 h = normalize (lightDir + viewDir);
				
				half diff = max (0, dot (s.Normal, lightDir));
				
				float nh = max (0, dot (s.Normal, h));
				float3 spec = pow (nh, s.Specular*128.0) * s.Gloss;
				
				half4 c;
				c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);
				c.a = s.Alpha + _LightColor0.a * Luminance(spec) * atten;
				return c;
			}
			
			inline half4 LightingBlinnPhongEditor_PrePass (EditorSurfaceOutput s, half4 light)
			{
				half3 spec = light.a * s.Gloss;
				
				half4 c;
				c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
				c.a = s.Alpha + Luminance(spec);
				return c;
			}
			
			struct Input {
float3 viewDir;

			};
			
samplerCUBE _SamplerCube0;

			void surf (Input IN, inout EditorSurfaceOutput o) {
				o.Albedo = 0.0;
				o.Normal = float3(0.0,0.0,1.0);
				o.Emission = 0.0;
				o.Gloss = 0.0;
				o.Specular = 0.0;
				o.Alpha = 1.0;
float4 TexCUBE0=texCUBE(_SamplerCube0,float4(IN.viewDir, 1.0));
float4 Master0_Normal_NoInput = float4(0,0,1,1);
float4 Master0_Emission_NoInput = float4(0,0,0,0);
float4 Master0_Specular_NoInput = float4(0,0,0,0);
float4 Master0_Gloss_NoInput = float4(0,0,0,0);
float4 Master0_Alpha_NoInput = float4(0,0,0,0);
float4 Multiply3=float4(IN.viewDir, 1.0) * float4( -1);
float4 TexCUBE1 = TexCUBE0 * float4( 1.0 - dot( normalize( float4(IN.viewDir, 1.0).xyz), normalize( Multiply3.xyz ) ) );
o.Albedo = TexCUBE1;
o.Normal = float3( 0.0, 0.0, 1.0);
o.Alpha = 1.0;

			}
		ENDCG
	}



CGINCLUDE
#pragma fragmentoption ARB_precision_hint_fastest
#pragma fragmentoption ARB_fog_exp2
#include "UnityCG.cginc"

sampler2D _GrabTexture : register(s0);
float4 _GrabTexture_TexelSize;
sampler2D _BumpMap : register(s1);
sampler2D _MainTex : register(s2);

struct v2f {
	float4 vertex : POSITION;
	float4 uvgrab : TEXCOORD0;
	float2 uvbump : TEXCOORD1;
	float2 uvmain : TEXCOORD2;
};

uniform float _BumpAmt;


half4 frag( v2f i ) : COLOR
{
	// calculate perturbed coordinates
	half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg; // we could optimize this by just reading the x  y without reconstructing the Z
	float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
	i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
	
	half4 col = tex2Dproj( _GrabTexture, i.uvgrab.xyw );
	half4 tint = tex2D( _MainTex, i.uvmain );
	return col * tint;
}
ENDCG

Category {

	// We must be transparent, so other objects are drawn before this one.
	Tags { "Queue"="Transparent" "RenderType"="Opaque" }


	SubShader {

		// This pass grabs the screen behind the object into a texture.
		// We can access the result in the next pass as _GrabTexture
		GrabPass {							
			Name "BASE"
			Tags { "LightMode" = "Always" }
 		}
 		
 		// Main pass: Take the texture grabbed above and use the bumpmap to perturb it
 		// on to the screen
		Pass {
			Name "BASE"
			Tags { "LightMode" = "Always" }
			
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

struct appdata_t {
	float4 vertex : POSITION;
	float2 texcoord: TEXCOORD0;
};

v2f vert (appdata_t v)
{
	v2f o;
	o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
	#if UNITY_UV_STARTS_AT_TOP
	float scale = -1.0;
	#else
	float scale = 1.0;
	#endif
	o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
	o.uvgrab.zw = o.vertex.zw;
	o.uvbump = MultiplyUV( UNITY_MATRIX_TEXTURE1, v.texcoord );
	o.uvmain = MultiplyUV( UNITY_MATRIX_TEXTURE2, v.texcoord );
	return o;
}
ENDCG
		}
	}
}
}

The right door has the functional glass, with lighting-aware transparency, normal-map distortion, etc.
The left door has the same code, but with a procedurally-generated cubemap included.
As you can see, the new shader’s cubemapping overrides almost everything else.

I was messing around with something like what you’re wanting. I’ve no idea how you’d go about getting it to work with yours or with Beast Lightmapping (I’m on 2.6.1) but it does allow for distortion via normal map, and a cubemap for faked reflection and that part works nicely together. I’m lost on the whole getting fresnel to work though, sorry. :frowning:

Hope this helps in some way though!

Shader "FX/Glass/Stained BumpDistorted Specular" {
	Properties {
		_Color ("Main Color", Color) = (1,1,1,0.5)
		_ReflectColor ("Reflection Color", Color) = (0.2,0.2,0.2,0)
		_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
		_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
		_BumpAmt  ("Distortion", range (0,128)) = 10
		_MainTex ("Tint Color (RGB)", 2D) = "white" {}
		_BumpMap ("Bumpmap (RGB)", 2D) = "bump" { }
      _Cube ("cubemap", Cube) = "_Skybox"
	} 
 
	SubShader {
		Tags { "Queue"="Transparent" "RenderType"="Opaque" }
		UsePass "FX/Glass/Stained BumpDistort/BASE"
		UsePass " BumpedSpecular/PPL"
		UsePass "Reflective/VertexLit/BASE"
	}
	
	// Fallback shader for older cards  non-PRO Unities.
	SubShader {
		Tags { "Queue"="Transparent" "RenderType"="Opaque" }
		Blend DstColor Zero
		Pass {
			Name "BASE"
			SetTexture [_MainTex] {	combine texture }
		}
	}
}

Thanks for the attempt, but it doesn’t work out (actually, for some reason, I can’t get any of your shader’s features to work properly for me, even in 2.6.1).

It’s given me a few ideas on which way I might go next, though (notably that I should look through the U3 versions of all the shaders that your version references).

btw, to anyone who’s reading this, do you know if it’s possible at all to combine surface shader code with vertex/fragment shader code in the same shader and have them both work?

Hmm, that is weird. I don’t know why it wouldn’t work for you. It seems fine here.

Uploaded with ImageShack.us

2.6.1 pro right?