Appearance
【法线贴图】
法线贴图
shader
// 在顶点着色器函数里构建切线空间的三个方向 TBN (v.normal是float3,v.tangent是float4)
o.normal = UnityObjectToWorldNormal( v.normal );
o.tangent = UnityObjectToWorldDir( v.tangent.xyz );// 使用Unity内置函数的方式
// o.tangent = normalize(mul(unity_ObjectToWorld,float4(v.tangent.xyz,0.0)).xyz);
o.btangent = cross( o.normal, o.tangent);
o.btangent *= v.tangent.w * unity_WorldTransformParams.w;// 处理翻转和镜像
// 在片段着色器里进行转换纹理贴图成向量
float3 tangentSpaceNormal = UnpackNormal( tex2D( _NormalTex, i.uv ) );
// 方式A
// 关于矩阵mul(pos,矩阵) 的矩阵先后顺序的问题
// 与Unity内置矩阵一致的方式,相乘时矩阵放[左侧]
float3x3 mtxTangToWord_A = float3x3(
i.tangent.x,i.btangent.x,i.normal.x,
i.tangent.y,i.btangent.y,i.normal.y,
i.tangent.z,i.btangent.z,i.normal.z);
float3 N_A = mul(mtxTangToWord_A,tangentSpaceNormal);
// 方式B
// 与Unity内置矩阵相反的方式,相乘时矩阵放[右侧],其实就是方式A的转置
float3x3 mtxTangToWord_B = float3x3(
i.tangent.x,i.tangent.y,i.tangent.z,
i.btangent.x,i.btangent.y,i.btangent.z,
i.normal.x,i.normal.y,i.normal.z);
// 与上面mtxTangToWord_B结果其实是一样的,这个是简写方式
float3x3 mtxTangToWord_B2 = float3x3(i.tangent,i.btangent,i.normal);
float3 N_B = mul(tangentSpaceNormal,mtxTangToWord_B);
高度图转法线图
shader
#define heightMap iChannel0
#define heightMapResolution iChannelResolution[0]
#define normalStrength 10.0
#define textureOffset 1.0
#define pixelToTexelRatio (iResolution.xy/heightMapResolution.xy)
vec2 stdNormalMap(in vec2 uv)
{
float height = texture(heightMap, uv).r;
return -vec2(dFdx(height), dFdy(height)) * pixelToTexelRatio;
}
vec2 texNormalMap(in vec2 uv)
{
vec2 s = 1.0/heightMapResolution.xy;
float p = texture(heightMap, uv).x;
float h1 = texture(heightMap, uv + s * vec2(textureOffset,0)).x;
float v1 = texture(heightMap, uv + s * vec2(0,textureOffset)).x;
return (p - vec2(h1, v1));
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy;
float mousePosition = (iMouse.x > 0.1) ? iMouse.x : iResolution.x * 0.5;
float mouseSplit = round(mousePosition * 0.5) * 2. + 1.;
if (abs(fragCoord.x - mouseSplit) < 1.0)
{
fragColor = vec4(0.);
return;
}
vec2 normal = (fragCoord.x > mouseSplit) ? texNormalMap(uv) : stdNormalMap(uv);
normal *= normalStrength;
normal += 0.5;
fragColor = vec4(normal, 1., 1.);
}
控制法线强度
shader
float3 tangentSpaceNormal = UnpackNormal( tex2D( _RockNormals, i.uv ) );
tangentSpaceNormal = normalize(lerp( float3(0,0,1), tangentSpaceNormal, _NormalIntensity ));