XNA BUMP MAPPING

  终于把这个效果做出来了。

  看了N久别人写的shader才明白,写的时候更是恼火。看来真的是验证了看shader容易,写shader复杂。

先看下纹理资源:

然后是普通贴图的效果:

 

从图中可以看出,这里是没有高低不平的感觉。以下是通过bump mapping的效果。

以下图作为bump

shader效果图:

接着看代码,程序代码:

Code
using CameraLib;

namespace bumpmapping
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

Model sphere;
Texture2D textureColor;
Texture2D textureBump;
Effect effect;

Camera camera;

public Game1()
{
graphics
= new GraphicsDeviceManager(this);
Content.RootDirectory
= "Content";
}

protected override void Initialize()
{
IsMouseVisible
= true;
camera
= new Camera(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 1, 1000,
new Vector3(0, 0, 100), Vector3.Forward, Vector3.Up,this.Window.ClientBounds);

base.Initialize();
}

protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

sphere
= Content.Load<Model>("bsphere");
textureColor
= Content.Load<Texture2D>("earth");
textureBump
= Content.Load<Texture2D>("earthbump");
effect
= Content.Load<Effect>("bump");
}

Matrix rollMatrix
= Matrix.Identity;
protected override void Update(GameTime gameTime)
{
#region 控制地球可以旋转

KeyboardState ks
= Keyboard.GetState();
Vector2 roll
= Vector2.Zero;
if (ks.IsKeyDown(Keys.NumPad4))
{
roll.X
+= 0.1f;
}
if (ks.IsKeyDown(Keys.NumPad6))
{
roll.X
-= 0.1f;
}
if (ks.IsKeyDown(Keys.NumPad8))
{
roll.Y
+= 0.1f;
}
if (ks.IsKeyDown(Keys.NumPad5))
{
roll.Y
-= 0.1f;
}
rollMatrix
*= Matrix.CreateFromYawPitchRoll(roll.X,roll.Y,0);
#endregion

camera.UpdateMatrix();
base.Update(gameTime);
}

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
effect.CurrentTechnique
= effect.Techniques[0];
effect.Parameters[
"matWorldViewProj"].SetValue(rollMatrix*camera.View * camera.Projection);
effect.Parameters[
"matWorld"].SetValue(rollMatrix);
effect.Parameters[
"vecLightDir"].SetValue(new Vector3(-100, -100,-100));
effect.Parameters[
"vecEye"].SetValue(camera.mposi);
effect.Parameters[
"ColorMap"].SetValue(textureColor);
effect.Parameters[
"BumpMap"].SetValue(textureBump);

graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

foreach(ModelMesh mesh in sphere.Meshes)
{
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect
= effect;
}

mesh.Draw();
}

base.Draw(gameTime);
}
}
}

HLSL顶点渲染器输出结构:

Code
// HLSL顶点渲染器输出结构
struct VS_OUTPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
float3 Light: TEXCOORD1;
//纹理空间中灯光方向
float3 View : TEXCOORD2; //纹理空间中法线方向
};

// 顶点渲染器主函数
VS_OUTPUT VS(float4 Pos : POSITION, float2 Tex : TEXCOORD, float3 Normal : NORMAL, float3 Tangent : TANGENT )
{
VS_OUTPUT Out
= (VS_OUTPUT)0;

//顶点坐标变换
Out.Pos = mul(Pos, matWorldViewProj);

//构建一个x3变换矩阵用于完成从世界空间到纹理空间的变换
float3x3 worldToTangentSpace;

worldToTangentSpace[
0] = mul(Tangent, matWorld);
worldToTangentSpace[
1] = mul(cross(Tangent,Normal), matWorld);
worldToTangentSpace[
2] = mul(Normal, matWorld);
Out.Tex
= Tex.xy;

//顶点在世界空间中的坐标
float3 PosWorld = normalize(mul(Pos, matWorld));

//计算纹理空间中灯光方向向量
float3 Light = vecLightDir - PosWorld;
Out.Light.xyz
= mul(worldToTangentSpace, Light);

//计算纹理空间中的观察方向
float3 Viewer = vecEye - PosWorld;
Out.View
= mul(worldToTangentSpace, Viewer);
return Out;
}

HLSL像素渲染器输出结构

Code
struct PS_OUTPUT
{
float4 Color : COLOR;
};


// 像素渲染器主函数
PS_OUTPUT PS(float2 Tex: TEXCOORD0, float3 Light : TEXCOORD1, float3 View : TEXCOORD2, float3 Att : TEXCOORD3)
{
PS_OUTPUT Out_ps
= (PS_OUTPUT)0;

//颜色纹理采样
float4 color = tex2D(ColorMapSampler, Tex);

//凹凸纹理采样, 得到的是法线向量, 用于代替顶点法线进行光照计算
float3 bumpNormal = 2 * (tex2D(BumpMapSampler, Tex) - 0.5);

//标准化纹理空间中的灯光方向和观察方向
float3 LightDir = normalize(Light);
float3 ViewDir
= normalize(View);

//根据凹凸贴图的发线进行漫反射光照计算
float4 diff = saturate(dot(bumpNormal, LightDir));

//计算自身遮蔽阴影项
float shadow = saturate(4 * diff);

//计算镜面反射强度
float3 Reflect = normalize(2 * diff * bumpNormal - LightDir);
float4 spec
= min(pow(saturate(dot(Reflect, ViewDir)), 15), color.a);

//混合纹理颜色和光照颜色, 得到每个像素的最终颜色
Out_ps.Color = 0.2 * color + (shadow * (color * diff + spec) );

return Out_ps;
}

 

 

posted @ 2008-10-04 22:13  齐.net  阅读(2172)  评论(2编辑  收藏  举报