What is Normal Mapping?
Normal-Mapping is a technique used to light a 3D model with a low polygon count as if it were a more detailed model. It does not actually add any detail to the geometry, so the edges of the model will still look the same, however the interior will look a lot like the high-res model used to generate the normal map. The RGB values of each texel in the the normal map represent the x,y,z components of the normalized mesh normal at that texel. Instead of using interpolated vertex normals to compute the lighting, the normals from the normal map texture are used
Tangent Space or Object Space
Normal can be saved directly as normal vector, or tangent and binormal along u/v directions in UV space.Create Normal Map
Once you have a high-res and low-res model, you'll need something to generate the normal map.
What has to be down programatically is to cast a ray from each texel on the low-res model, find the ray's intersection with the high-res model, and save in a texture map the normal from the high-res model where the ray intersects.
ATI and NVidia have existing tools for normal map.
Use Normal map
In OpenGL
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGBA_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
In HLSL
===============Vertex Shader===========================
void main(
float4 Pobject : POSITION,
float2 TexUV : TEXCOORD0,
float3 inL : COLOR0,
uniform float4x4 ModelViewProj,
uniform float3 lightPosOS, // OS = in Object Space
uniform float lQ, // Light intensity, for distance attenuation
uniform half3 lightColor,
out float4 HPosition : POSITION,
out half4 L : COLOR0,
out float2 uv : TEXCOORD0,
out half3 LV : TEXCOORD1 )
{
HPosition = mul(ModelViewProj, Pobject);
uv = TexUV;
LV.xyz = inL;
float d = distance( lightPosOS, Pobject );
L.xyz = lightColor * saturate ( 1.0 / (lQ * d * d) );
}
===============Pixel Shader===========================
//
// lColor = light color, uv = texture coordinates for normal map and diffuse map,
// LV = light vector, the ambientColor constant is set with cgGLSetParameter3fv.
//
half4 main(
half4 lColor : COLOR0,
half2 uv : TEXCOORD0,
half3 LV : TEXCOORD1,
uniform sampler2D diffuseMap : TEXUNIT0,
uniform sampler2D normalMap : TEXUNIT1,
uniform half3 ambientColor) : COLOR
{
half3 N = tex2D( normalMap, uv ).xyz * 2.0 -1.0;
half NdotL = saturate( dot(N, LV * 2.0 - 1.0) );
half3 C = saturate( lColor * NdotL + ambientColor ) * (half3)tex2D(diffuseMap, uv).xyz;
return half4(C, 1);
}
No comments:
Post a Comment