- Home /
How to use the alpha channel of bump map, as transparency.
I'm having trouble with a shader i've written. up until now everything seems to work the way i want it to work, and i'm happy with my progress. this is my first time writing a shader, and i've not got any programming or code background... so please bear with me. i'm just a character artist trying to expand his skillset!
so anyway, i need the alpha channel of the normalmap to act as the transparency mask, with a slider to control the transparency cutoff. the slider works just fine, and if i use the diffuse alpha channel, that works great. but the diffuse alpha is actually for something else, so it MUST be the normalmap alpha. but it just refuses to work.
chances are i'm making a rookie mistake that i just haven't seen yet.
so please, if anyone can help i'd be very grateful! here's the shader so far:
Shader "custom/global shader"
{
Properties
{
//lay out like this: maptype ("UI name", function) = "
//Color multiplies diffuse texture, useful for tinting.
_Color ("Diffuse tint", COLOR) = (1,1,1)
//Maintex is the diffuse texture we call up.
_MainTex ("Diffuse texture", 2D) = "white" {}
//Transparency slider defines alpha cutoff value
_Transparency ("Transparency", Range (0.0, 1.0)) = 1
//MaskTex has multiple functions - Red = Rim strength, Green = Rim broadness, Blue = Diffuse tint mask
_MaskTex ("Effect masks", 2D) = "white" {}
//WrapAmount is half lambert amount
_WrapAmount ("Half Lambert", Range (0.0, 1.0)) = 0.5
//bumpmap is normalmap
_BumpMap ("Normalmap", 2D) = "white" {}
//Emmission slider to control the brightness of full emmission.
_Emission ("Emission", Range (0.0, 2.0)) = 0
//RimStrength can multiply rimlight to zero. also defines the maximum rim strength.
_RimStrength ("Rimlight Strength", Range (0,2)) = 1
//RimColor is rim light colour, and RimPower is broadness + brightness of rim light. also defines maximum broadness of the rim light.
_RimColor ("Rim Color", Color) = (1,1,1,0.0)
_RimPower ("Rim Broadness", Range(0.5,8.0)) = 3.0
//Rim-tint is a test to see if we can have a portion of the shader dedicated to metallics specifically.
_RimTint ("Rim tint", Range(0.0,1.0)) = 1.0
}
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
LOD 200
CGPROGRAM
//defines the surface types for the material.
#pragma surface surf WrapLambert alphatest:_Transparency
//defines half lambert strength. closer to 0 - more strongly lit.
float _WrapAmount;
half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half diff = NdotL * _WrapAmount + (1 - _WrapAmount);
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
c.a = s.Alpha;
return c;
}
struct Input {
//"should" define a colour to tint diffuse with
float3 _Color;
//calls textures to be used
float2 uv_MainTex;
float2 uv_BumpMap;
float2 uv_MaskTex;
//defines camera direction in relation to object
float3 viewDir;
};
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _MaskTex;
float3 _Color;
float _Emission;
float4 _RimColor;
float _RimPower;
float _RimStrength;
float _RimTint;
void surf (Input IN, inout SurfaceOutput o) {
// cache the texture lookups
// the line below creates a new local variable (it will not exist outside this function, and once the function is finished, it will be removed from memory) and fill it with the result of the texture lookup
// this means that the variable main will have 4 components, r, g, b and a. Which you can use at your whim. :)
float4 main = tex2D(_MainTex, IN.uv_MainTex);
float4 mask = tex2D(_MaskTex, IN.uv_MaskTex);
float4 bump = tex2D(_BumpMap, IN.uv_BumpMap);
//Albedo = final unlit colour map, in this case combination of diffuse map * diffuse tint. tint map can be masked.
o.Albedo = lerp(main.rgb, main.rgb * _Color, main.a);
o.Normal = UnpackNormal (bump);
//Alpha channel in normal map is transparency
o.Alpha = bump.a;
//Rimlight calculation is emmissive.
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
//Can now transition between coloured rim light, and metallic rim light, keep rim tint slider at 0 for non-metallic surfaces.
o.Emission = ((mask.a * main.rgb) * _Emission + (lerp(_RimColor.rgb, main.rgb * 2.0, _RimTint * mask.b) * pow (rim, _RimPower * mask.g)) * (_RimStrength * mask.r));
}
ENDCG
Pass {
//first render pass.
Tags { "RenderType" = "Transparent" }
//Lighting function turns on/off, defaults to off if function not present.
Lighting ON
}
}
}
Answer by Owen-Reynolds · Dec 07, 2012 at 03:41 PM
You probably only have a single unwrap, so could just get rid of `uv_BumpMap` and use `uv_MainTex` for everything. I've had trouble getting it to hook an unwrap up with anything but the first texture -- was just all 0's.
Could test by doing things like `o.Albedo=IN.uv_bump.x` or `if(bump.a>0.5) o.Albedo=1; else o.Albedo=0;`
That lets you track down whether it can read the uvs, and whether bump alpha is being read.
Answer by Almighty_gir · Jan 08, 2013 at 02:23 PM
I managed to solve this by changing the way unity brings in the bumpmap, instead of calling it as a bumpmap, it calls it as a texture, and then you set it (in the shader) to display the same way a bumpmap should.
it's important that you ignore any warnings of "this texture is not set to bumpmap, do you want to fix this now?" while using this method.
here is the code for it, hope this helps other people!:
void surf (Input IN, inout MySurfaceOutput o) {
half4 bump = tex2D(_BumpMap, IN.uv_BumpMap);
o.Normal = bump.xyz * 2 - 1;
}