在FX Composer里面实现的,先给大家看看效果对比图:
视差贴图
普通法线贴图
啥也没有的普通着色
由于光源是动态移动的,所以会有所不同。不过已经可以明显的看出视差贴图比法线贴图更加具有立体感,当然它并不是真的有立体效果,而是我们的眼睛欺骗了我们。当我们把视角拉平的时候就能看出来它原来是平的:
任何好处的获得都是要付出一定的代价的,相对法线贴图而言,视差贴图要多一些小步骤,当然,个人认为这并不能阻碍我们使用它。
至于没有特殊效果的着色是最简单的,不过效果当然不能比哦~
下面是代码:
/**
* @brief a simple implement of normal-mapping and parallax-mapping.
* @author dongbo
* @date 2010.10.21
* @remarks http://hi.baidu.com/_%E2d_%B7%B3_%DE%B2%C2%D2
*/
float4x4 matWorldViewProj : WorldViewProjection;
float4x4 matWorld : World;
float4x4 matWorldIT : WorldInverseTranspose;
float4x4 matViewIX : ViewInverse;
struct VS_Input
{
float4 Position : POSITION;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
float2 Tex : TEXCOORD0;
};
struct VS_Output
{
float4 Pos : POSITION;
float3 Normal : NORMAL;
float2 Tex : TEXCOORD0;
float3 LightDir : TEXCOORD1;
float3 ViewDir : TEXCOORD2;
};
float3 g_WorldLightPos : POSITION
<
string object = "pointlight";
string space = "world";
string UIName = "Light0 Position";
>;
float g_fSpeed<
string UIName = "Light Speed";
string UIWidget = "Slider";
float UIMax = 10;
float UIMin = 0.0f;
float UIStep = 1.0f;
> = 0.0f;
float g_fTime : TIME;
float g_fSelfShadowParam<
string UIName = "Self Shadow Param";
string UIWidget = "Slider";
float UIMax = 10;
float UIMin = 0.0;
float UIStep = 0.5;
> = 4.0f;
float g_fSpecExp<
string UIName = "Spec Exp";
string UIWidget = "Slider";
float UIMax = 100;
float UIMin = 0;
float UIStep = 1;
> = 20;
texture g_NormalTexture<
string UIName = "NormalTex";
string ResourceName = "normalMap.bmp";
>;
sampler g_NormalSmapler = sampler_state
{
Texture = <g_NormalTexture>;
AddressU = Wrap;
AddressV = Wrap;
MinFilter = Linear;
MipFilter = Linear;
MipFilter = Linear;
};
texture g_HeightTexture<
string UIName = "HeightTex";
string ResourceName = "heightMap.bmp";
>;
sampler g_HeightSampler = sampler_state
{
Texture = <g_HeightTexture>;
AddressU = Wrap;
AddressV = Wrap;
MinFilter = Linear;
MipFilter = Linear;
MipFilter = Linear;
};
texture g_ColorTexture<
string UIName = "ColorTex";
string ResourceName = "colorMap.bmp";
>;
sampler g_ColorSmapler = sampler_state
{
Texture = <g_ColorTexture>;
AddressU = Wrap;
AddressV = Wrap;
MinFilter = Linear;
MipFilter = Linear;
MipFilter = Linear;
};
VS_Output mainVS( VS_Input input )
{
VS_Output output = (VS_Output)0;
output.Pos = mul( input.Position, matWorldViewProj );
output.Tex = input.Tex;
// copy from google. thanks google.
float3x3 worldToTangentSpace;
worldToTangentSpace[0] = mul( input.Tangent, matWorld);
worldToTangentSpace[1] = mul( cross( input.Tangent, input.Normal ), matWorld );
worldToTangentSpace[2] = mul( input.Normal, matWorld );
float3 WorldPos = mul( input.Position, matWorld ).xyz;
float3 WorldView = normalize( matViewIX[3].xyz - WorldPos );
output.ViewDir = normalize( mul( worldToTangentSpace, WorldView ) );
float3 WorldLightPos = g_WorldLightPos;
WorldLightPos.x += sin( g_fTime ) * g_fSpeed;
WorldLightPos.z += cos( g_fTime ) * g_fSpeed;
float3 LightDir = normalize( WorldLightPos - WorldPos );
output.LightDir = normalize( mul( worldToTangentSpace, LightDir ) );
float3 WorldNormal = mul( input.Normal, matWorldIT );
output.Normal = normalize( mul( worldToTangentSpace, WorldNormal ) );
return output;
}
float4 StandardLighting(
float3 Normal,
float3 LightDir,
float3 ViewDir,
float2 Tex
)
{
float4 color = tex2D( g_ColorSmapler, Tex );
LightDir = normalize( LightDir );
ViewDir = normalize( ViewDir );
Normal = normalize( Normal );
float4 diffuse = saturate( dot( Normal, LightDir ) );
float fShadow = saturate( g_fSelfShadowParam * diffuse );
float3 Reflect = normalize( 2 * diffuse * Normal - LightDir );
float4 Spec = min( pow( saturate( dot( Reflect, ViewDir ) ), g_fSpecExp ), color. a );
color = color * 0.5 + fShadow * ( color * diffuse + Spec );
return color;
}
float4 mainPS_Normal( VS_Output input ) : COLOR
{
float4 color = StandardLighting( input.Normal, input.LightDir, input.ViewDir, input.Tex );
return color;
}
float4 mainPS_NormalMapping( VS_Output input ) : COLOR
{
float4 color = {1.0f,1.0f,1.0f,1.0f};
float3 Normal = 2 * ( tex2D( g_NormalSmapler, input.Tex ) - 0.5 );
color = StandardLighting( Normal, input.LightDir, input.ViewDir, input.Tex );
return color;
}
float g_Scale <
string UIName = "Parallax Scale";
string UIWidget = "Slider";
float UIMax = 0.1f;
float UIMin = 0.0f;
float UIStep = 0.001f;
> = 0.0f;
float g_Bias <
string UIName = "Parallax Bias";
string UIWidget = "Slider";
float UIMax = 0.1f;
float UIMin = -0.1f;
float UIStep = 0.001f;
> = 0.0f;
float4 mainPs_Parallaxmapping( VS_Output input ) : COLOR
{
float4 color = {1.0f,1.0f,1.0f,1.0f};
float4 height = g_Scale * tex2D( g_HeightSampler, input.Tex ) - g_Bias;
float2 texNew= input.ViewDir * height + input.Tex;
float3 Normal = 2 * ( tex2D( g_NormalSmapler, texNew ) - 0.5 );
color = StandardLighting( Normal, input.LightDir, input.ViewDir, texNew );
return color;
}
technique normalMapping
{
pass p0
{
CullMode = None;
VertexShader = compile vs_3_0 mainVS();
PixelShader = compile ps_3_0 mainPS_NormalMapping();
}
}
technique ParallaxMapping
{
pass p0
{
CullMode = None;
VertexShader = compile vs_3_0 mainVS();
PixelShader = compile ps_3_0 mainPs_Parallaxmapping();
}
}
technique NormalEffect
{
pass
{
CullMode = None;
VertexShader = compile vs_3_0 mainVS();
PixelShader = compile ps_3_0 mainPS_Normal();
}
}
PS:晚上回来心血来潮无聊弄的,可能有Bug或者不严谨的地方,大家原谅则个~