Hello everybody,
For the project I’m working on, I need a shader capable of combining two diffuse textures and apply a normal map on it for the lightning.
I’m new to shader creation using CG, but I managed to make something work, approximately.
Here is my code :
Shader "@My Normal Multi" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_SecondaryTex ("Second (RGB) Mask(A)", 2D) = "white" {}
_BumpMap ("Bumpmap (RGB)", 2D) = "bump" {}
_TestColor ("Test Color" , Color) = (0.5,0.5,0.5,1)
_NormalIntensity ("Normal intensity", Range(0,1)) = 0.5
_BlendFloat ("Blending", Range(0,1)) = 0.5
_NormalMask ("Normal Mask", Range(0,1)) = 0.5
}
Category {
Tags { "RenderType"="Opaque" }
LOD 300
Blend AppSrcAdd AppDstAdd
Fog { Color [_AddFog] }
// ------------------------------------------------------------------
// ARB fragment program
SubShader {
// Pixel lights
Pass {
Name "PPL"
Tags { "LightMode" = "Pixel" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_builtin
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f {
V2F_POS_FOG;
LIGHTING_COORDS
float2 uv;
float2 uv2;
float2 uvBump;
float3 lightDirT;
float3 viewDirT;
float3 Normal;
float4 NormalColor : COLOR;
};
uniform float4 _MainTex_ST, _BumpMap_ST, _SecondaryTex_ST;
//get vertex data : texture coordinates 01, position, normal, tangent
struct appdata {
float4 texcoord;
float4 texcoord1;
float4 vertex;
float3 normal;
float4 tangent;
};
uniform float4 _MainColor;
uniform float4 _TestColor;
uniform float _NormalIntensity;
uniform float _BlendFloat;
uniform float _NormalMask;
uniform sampler2D _MainTex, _SecondaryTex, _BumpMap;
v2f vert (appdata v)
{
v2f o;
PositionFog( v.vertex, o.pos, o.fog );
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv2 = TRANSFORM_TEX(v.texcoord1,_SecondaryTex);
o.uvBump = TRANSFORM_TEX(v.texcoord,_BumpMap);
o.Normal = v.normal;
o.NormalColor = float4(v.tangent.xyz*0.5+0.5, 1);
TANGENT_SPACE_ROTATION;
o.lightDirT = mul( rotation, ObjSpaceLightDir( v.vertex ) );
o.viewDirT = mul( rotation, ObjSpaceViewDir( v.vertex ) );
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
//Light using the normal map
float4 frag (v2f i) : COLOR
{
float4 MainColor = tex2D(_MainTex,i.uv);
float4 SecondColor = tex2D(_SecondaryTex,i.uv2);
float4 NormalMap = tex2D(_BumpMap, i.uvBump);
float coef = SecondColor.a*_BlendFloat;
float4 texcol = lerp (MainColor, SecondColor, coef);
//mask the normal map with a (0.0.1) normal (local to uv) using the vertex normal color
float4 NormalColor = lerp (NormalMap, float4(0.5,0.5,1,1), coef*_NormalMask);
//Attenuate the normal
NormalColor = lerp (NormalColor, float4(0.5,0.5,1,1),1-_NormalIntensity);
// get normal from the normal color
float3 normal = NormalColor.xyz * 2 - 1;
half4 Light = DiffuseLight( i.lightDirT, normal, texcol, LIGHT_ATTENUATION(i) );
return Light;
}
ENDCG
}
}
}
FallBack "Diffuse", 1
}
It seams to work well, but I have a few problemw with it.
First, with this part :
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv2 = TRANSFORM_TEX(v.texcoord1,_SecondaryTex);
o.uvBump = TRANSFORM_TEX(v.texcoord,_BumpMap);
o.Normal = v.normal;
o.NormalColor = float4(v.tangent.xyz*0.5+0.5, 1);
I first wanted to use the vertex local normals in order to attenuate the original normal map (so we can have a little tweak for the normal intensity), but it seems that when using texcoord AND texcoord1, the vertex normals are getting messed up (I saw they tried to match something like : normal = uv2).
Is there a proper way to attenuate the normals ?
Second :
My actual shader is affected by only one light, does somebody know why ?
I don’t know if I’m using the best actual method to do what I want, so, if anybody has an answer for my questions, or a better way to do all this stuff, I’m open for any suggestions :).