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:
// Test shader, trying to write my own shit//
Shader "custom/CapeChronicles 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
}
}
}
P.S. this is a unity shader, not sure if that makes too much of a difference.
Replies
If you select your normal map texture, it's most likely got its Texture Type set to Normal Map. Which seems sensible, except that there are no options in there that allow for an explicit alpha channel. So what you'll want to do is set your normal map to "Texture".
Then in your shader, swap out UnpackNormal for:
Now if you've set your Color Space (in player options) to Linear, then your tex2d code should be:
it now seems like the rimlight isn't a rimlight anymore, it's now directional. or at least it looks that way on the preview shader.
(quick side note: For your normal map texture parameter, you should use [= "bump"] instead of [= "white"], so that Unity assumes a default 128,128,255 color when nothing is assigned)
With the above shader, I get the following: