我正在使用 C#/XNA 4.0 制作游戏。
所以我有一个用 3DSMax 制作的简单盒子
http://i.imgur.com/gd65sTx.png
我缩放它
Vector3 scaleVector = new Vector3(width, 1, height);
Matrix newMatrix = scale * translationMatrix;
结果如下:
http://i.imgur.com/YNAIr8y.png
这是我的渲染方法:
/// <summary>
/// Draws an objects with the specified texture. This DOES change the current textures, so be careful!
/// </summary>
public static void DrawModel(GraphicsDevice gd, Model model,
RenderTechnique technique, Vector3 cameraPosition,
Matrix world, Matrix viewProjection, LightList lights, Texture2D texture)
{
SetTexture(texture, model);
DrawModel(gd, model, technique, cameraPosition, world, viewProjection, lights);
}
/// <summary>
/// Sets a texture for a model by changing the effect parameters
/// </summary>
public static void SetTexture(Texture2D texture, Model model)
{
// for each mesh in model
foreach (ModelMesh mesh in model.Meshes)
{
// for each mesh part
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// if primitives to change
if (meshPart.PrimitiveCount > 0)
{
// set texture visa effect
Effect effect = meshPart.Effect;
effect.Parameters["Texture"].SetValue(texture);
}
}
}
}
/// <summary>
/// Main Draw method. All draw calls end up here eventually.
/// </summary>
public static void DrawModel(GraphicsDevice gd, Model model,
RenderTechnique technique, Vector3 cameraPosition,
Matrix world, Matrix viewProjection, LightList lights)
{
if (gd == null)
{
throw new ArgumentNullException("gd");
}
// get model bones
model.CopyAbsoluteBoneTransformsTo(bones);
BlendState bs = gd.BlendState;
DepthStencilState ds = gd.DepthStencilState;
gd.DepthStencilState = DepthStencilState.DepthRead;
gd.BlendState = BlendState.Additive;
// for each mesh in model
foreach (ModelMesh mesh in model.Meshes)
{
// get mesh world matrix
Matrix worldBone = bones[mesh.ParentBone.Index] * world;
Matrix worldBoneInverse = Matrix.Invert(worldBone);
// compute camera position in object space
Vector3 cameraObjectSpace = cameraPosition - worldBone.Translation;
cameraObjectSpace = Vector3.TransformNormal(cameraObjectSpace,
worldBoneInverse);
gd.SamplerStates[0] = SamplerState.LinearWrap;
// for each mesh part
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// if primitives to render
if (meshPart.PrimitiveCount > 0)
{
// setup vertices and indices
gd.SetVertexBuffer(meshPart.VertexBuffer);
gd.Indices = meshPart.IndexBuffer;
// setup effect
Effect effect = meshPart.Effect;
effect.Parameters["WorldViewProj"].SetValue(worldBone * viewProjection);
effect.Parameters["CameraPosition"].SetValue(cameraObjectSpace);
// setup technique
effect.CurrentTechnique =
meshPart.Effect.Techniques[(int)technique];
// if not lights specified
if (lights == null)
{
// begin effect
effect.CurrentTechnique.Passes[0].Apply();
// draw with plain mapping
gd.DrawIndexedPrimitives(PrimitiveType.TriangleList,
meshPart.VertexOffset, 0, meshPart.NumVertices,
meshPart.StartIndex, meshPart.PrimitiveCount);
gd.SetVertexBuffer(null);
gd.Indices = null;
}
else
{
gd.DepthStencilState = DepthStencilState.Default;
gd.BlendState = BlendState.Opaque;
// get light effect parameters
EffectParameter effectLightPosition =
effect.Parameters[1];
EffectParameter effectLightColor =
effect.Parameters[2];
EffectParameter effectLightAmbient =
effect.Parameters[3];
// ambient light
Vector3 ambient = lights.ambient;
// for each light
foreach (Light light in lights.lights)
{
// setup light in effect
effectLightAmbient.SetValue(ambient);
light.SetEffect(effectLightPosition,
effectLightColor, worldBoneInverse);
// begin effect
effect.CurrentTechnique.Passes[0].Apply();
// draw primitives
gd.DrawIndexedPrimitives(PrimitiveType.TriangleList,
meshPart.VertexOffset, 0, meshPart.NumVertices,
meshPart.StartIndex, meshPart.PrimitiveCount);
// setup additive blending with no depth write
gd.DepthStencilState = DepthStencilState.DepthRead;
gd.BlendState = BlendState.Additive;
// clear ambinet light (applied in first pass only)
ambient = Vector3.Zero;
}
// clear vertices and indices
gd.SetVertexBuffer(null);
gd.Indices = null;
}
}
}
}
gd.DepthStencilState = ds;
gd.BlendState = bs;
}
这是我正在使用的着色器:
float4x4 WorldViewProj;
float4 LightPosition;
float3 LightColor;
float3 LightAmbient;
float3 CameraPosition;
texture2D Texture;
sampler2D TextureSampler = sampler_state
{
Texture = <Texture>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
sampler2D TextureSamplerClamp = sampler_state
{
Texture = <Texture>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
AddressU = clamp;
AddressV = clamp;
};
texture2D Bump0;
sampler2D NormalSampler = sampler_state
{
Texture = <Bump0>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
texture2D Specular0;
sampler2D SpecularSampler = sampler_state
{
Texture = <Specular0>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
texture2D Emissive0;
sampler2D GlowMapSampler = sampler_state
{
Texture = <Emissive0>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
textureCUBE Reflect;
samplerCUBE ReflectSampler = sampler_state
{
Texture = <Reflect>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
AddressU = clamp;
AddressV = clamp;
AddressW = clamp;
};
void PlainMappingVS(
in float4 InPosition : POSITION0,
in float2 InTexCoord : TEXCOORD0,
out float4 OutPosition : POSITION0,
out float2 OutTexCoord : TEXCOORD0 )
{
OutPosition = mul(InPosition, WorldViewProj);
OutTexCoord = InTexCoord;
}
float4 PlainMappingPS( in float2 TexCoord : TEXCOORD0 ) : COLOR0
{
return tex2D(TextureSampler, TexCoord);
}
void NormalMappingVS(
in float4 InPosition : POSITION0,
in float2 InTexCoord : TEXCOORD0,
in float3 InNormal : NORMAL0,
in float3 InBinormal : BINORMAL0,
in float3 InTangent : TANGENT0,
out float4 OutPosition : POSITION0,
out float2 OutTexCoord : TEXCOORD0,
out float3 OutLightDir : TEXCOORD1,
out float3 OutViewDir : TEXCOORD2,
out float3 OutReflectDir : TEXCOORD3 )
{
OutPosition = mul(InPosition, WorldViewProj);
OutTexCoord = InTexCoord;
float3x3 tangent_space = float3x3(InTangent, InBinormal, InNormal);
OutLightDir = mul(tangent_space, LightPosition.xyz - InPosition.xyz);
OutViewDir = mul(tangent_space, CameraPosition - InPosition.xyz);
OutReflectDir = reflect(InPosition.xyz - CameraPosition, InNormal);
}
float4 NormalMappingPS(
in float2 TexCoord : TEXCOORD0,
in float3 LightDir : TEXCOORD1,
in float3 ViewDir : TEXCOORD2,
in float3 ReflectDir : TEXCOORD3 ) : COLOR0
{
float4 diffuse = tex2D(TextureSampler, TexCoord);
float4 specular = tex2D(SpecularSampler, TexCoord);
float4 normal = tex2D(NormalSampler, TexCoord);
float3 reflect = texCUBE(ReflectSampler, ReflectDir);
float4 glow = tex2D(GlowMapSampler, TexCoord);
float3 n = normalize(normal.xyz - 0.5);
float3 l = normalize(LightDir);
float3 v = normalize(ViewDir);
float3 h = normalize(l+v);
float ndotl = saturate(dot(n,l));
float ndoth = saturate(dot(n,h));
if (ndotl == 0) ndoth = 0;
float3 ambient = LightAmbient * diffuse.xyz;
specular.xyz *= LightColor * pow(ndoth, specular.w * 255);
diffuse.xyz *= LightColor * ndotl;
reflect *= 1 - normal.w;
float glow_intensity = saturate(dot(glow.xyz, 1.0) + dot(specular.xyz, 1.0));
float4 color;
color.xyz = ambient + glow.xyz + diffuse.xyz + specular.xyz + reflect.xyz;
color.w = glow_intensity;
return color;
}
void ViewMappingVS(
in float4 InPosition : POSITION0,
in float3 InNormal : NORMAL0,
out float4 OutPosition : POSITION0,
out float OutFacing : TEXCOORD0 )
{
OutPosition = mul(InPosition, WorldViewProj);
float3 view = normalize(CameraPosition - InPosition.xyz);
OutFacing = saturate(dot(view, InNormal));
}
float4 ViewMappingPS(in float Facing : TEXCOORD0) : COLOR0
{
Facing *= Facing;
Facing *= Facing;
float4 tex = tex2D(TextureSamplerClamp, float2(Facing, 0));
tex.w = 1.0f;
return tex;
}
Technique PlainMapping
{
Pass
{
VertexShader = compile vs_1_1 PlainMappingVS();
PixelShader = compile ps_2_0 PlainMappingPS();
}
}
Technique NormalMapping
{
Pass
{
VertexShader = compile vs_1_1 NormalMappingVS();
PixelShader = compile ps_2_0 NormalMappingPS();
}
}
Technique ViewMapping
{
Pass
{
VertexShader = compile vs_1_1 ViewMappingVS();
PixelShader = compile ps_2_0 ViewMappingPS();
}
}
但是有两件事并没有像我希望的那样进行。首先,我想在盒子尺寸增加时平铺纹理。其次,它的灯光似乎很不稳定。我正在使用教育目录中 Ship Game 中的 Normal Lighting。
任何想法与照明发生了什么?或者我可以如何平铺纹理?