我的照明效果很好,除了立方体上的一张脸。我想我是通过将一些UV坐标归零来找到有问题的脸的。就像这些面孔在通过其他人显示。
我的着色器
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif
float4x4 WorldMatrix;
float4x4 ViewMatrix;
float4x4 ProjectionMatrix;
float4 AmbienceColor = float4(0.1f, 0.1f, 0.1f, 1.0f);
// For Diffuse Lightning
float4x4 WorldInverseTransposeMatrix;
float3 DiffuseLightDirection = float3(-1.0f, 0.0f, 0.0f);
float4 DiffuseColor = float4(1.0f, 1.0f, 1.0f, 1.0f);
// For Texture
texture ModelTexture;
sampler2D TextureSampler = sampler_state {
Texture = (ModelTexture);
MagFilter = Linear;
MinFilter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
struct VertexShaderInput
{
float4 Position : SV_POSITION0;
// For Diffuse Lightning
float4 NormalVector : NORMAL0;
// For Texture
float2 TextureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float4 NormalVector : NORMAL0;
float2 TextureCoordinate : TEXCOORD0;
};
VertexShaderOutput MainVS(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, WorldMatrix);
float4 viewPosition = mul(worldPosition, ViewMatrix);
output.Position = mul(viewPosition, ProjectionMatrix);
// For Diffuse Lightning
output.NormalVector = mul(input.NormalVector, WorldInverseTransposeMatrix);
// For Texture
output.TextureCoordinate = input.TextureCoordinate;
return output;
}
float4 MainPS(VertexShaderOutput input) : COLOR0
{
float4 color = AmbienceColor;
float lightIntensity = dot(input.NormalVector, -DiffuseLightDirection);
color += saturate(DiffuseColor * lightIntensity);
return saturate(color) * tex2D(TextureSampler, input.TextureCoordinate);
}
technique BasicColorDrawing
{
pass P0
{
VertexShader = compile VS_SHADERMODEL MainVS();
PixelShader = compile PS_SHADERMODEL MainPS();
}
};
生成矩阵和加载内容的代码
var myEffect = Content.Load<Effect>("Effects/File");
var checkerboardTexture = Content.Load<Texture2D>("Textures/T_GrandCanyonGround_01_BC");
effect.AmbientLightColor = new Vector3(0.5f, 0.5f, 0.5f); // a red light
myEffect.Parameters["AmbienceColor"].SetValue(new Vector4(0.5f, 0.5f, 0.5f, 1)); // a red light
myEffect.Parameters["DiffuseLightDirection"].SetValue(new Vector3(1, 0, 0.2f)); // coming along the x-axis
var camTarget = new Vector3(0f, 0f, 0f);
var camPosition = new Vector3(0f, 0f, -100f);
var projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45f),
GraphicsDevice.DisplayMode.AspectRatio,
1f, 1000f);
var viewMatrix = Matrix.CreateLookAt(camPosition, camTarget,
new Vector3(0f, 1f, 0f));// Y up
var worldMatrix = Matrix.CreateWorld(camTarget, Vector3.
Forward, Vector3.Up);
myEffect.Parameters["WorldMatrix"].SetValue(worldMatrix);
myEffect.Parameters["ProjectionMatrix"].SetValue(projection);
Matrix worldInverseTransposeMatrix = Matrix.Transpose(Matrix.Invert(worldMatrix));
myEffect.Parameters["WorldInverseTransposeMatrix"].SetValue(worldInverseTransposeMatrix);
绘制立方体的代码
private void DrawCubes()
{
blocks = new List<VertexPositionNormalTexture[]>(squareGrid.squares.GetLength(0) * squareGrid.squares.GetLength(1));
// Normal vectors for each face (needed for lighting / display)
Vector3 normalFront = new Vector3(0.0f, 0.0f, 1.0f);
Vector3 normalBack = new Vector3(0.0f, 0.0f, -1.0f);
Vector3 normalTop = new Vector3(0.0f, 1.0f, 0.0f);
Vector3 normalBottom = new Vector3(0.0f, -1.0f, 0.0f);
Vector3 normalLeft = new Vector3(-1.0f, 0.0f, 0.0f);
Vector3 normalRight = new Vector3(1.0f, 0.0f, 0.0f);
// UV texture coordinates
Vector2 textureTopLeft = new Vector2(1.0f, 0.0f);
Vector2 textureTopRight = new Vector2(0.0f, 0.0f);
Vector2 textureBottomLeft = new Vector2(1.0f, 1.0f);
Vector2 textureBottomRight = new Vector2(0.0f, 1.0f);
for (int i = 0; i < 3; i++)
{
Vector3 Position = new Vector3(i * 40, 0, 0);
var Size = 20;
// Calculate the position of the vertices on the top face.
Vector3 topLeftFront = Position + new Vector3(-1.0f, 1.0f, -1.0f) * Size;
Vector3 topLeftBack = Position + new Vector3(-1.0f, 1.0f, 1.0f) * Size;
Vector3 topRightFront = Position + new Vector3(1.0f, 1.0f, -1.0f) * Size;
Vector3 topRightBack = Position + new Vector3(1.0f, 1.0f, 1.0f) * Size;
// Calculate the position of the vertices on the bottom face.
Vector3 btmLeftFront = Position + new Vector3(-1.0f, -1.0f, -1.0f) * Size;
Vector3 btmLeftBack = Position + new Vector3(-1.0f, -1.0f, 1.0f) * Size;
Vector3 btmRightFront = Position + new Vector3(1.0f, -1.0f, -1.0f) * Size;
Vector3 btmRightBack = Position + new Vector3(1.0f, -1.0f, 1.0f) * Size;
VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[36];
//FRONT face.
vertices[0] = new VertexPositionNormalTexture(topLeftFront, normalFront, textureTopLeft);
vertices[1] = new VertexPositionNormalTexture(btmLeftFront, normalFront, textureBottomLeft);
vertices[2] = new VertexPositionNormalTexture(topRightFront, normalFront, textureTopRight);
vertices[3] = new VertexPositionNormalTexture(btmLeftFront, normalFront, textureBottomLeft);
vertices[4] = new VertexPositionNormalTexture(btmRightFront, normalFront, textureBottomRight);
vertices[5] = new VertexPositionNormalTexture(topRightFront, normalFront, textureTopRight);
//BACK face.
vertices[6] = new VertexPositionNormalTexture(topLeftBack, normalBack, textureTopRight);
vertices[7] = new VertexPositionNormalTexture(topRightBack, normalBack, textureTopLeft);
vertices[8] = new VertexPositionNormalTexture(btmLeftBack, normalBack, textureBottomRight);
vertices[9] = new VertexPositionNormalTexture(btmLeftBack, normalBack, textureBottomRight);
vertices[10] = new VertexPositionNormalTexture(topRightBack, normalBack, textureTopLeft);
vertices[11] = new VertexPositionNormalTexture(btmRightBack, normalBack, textureBottomLeft);
//TOP face.
vertices[12] = new VertexPositionNormalTexture(topLeftFront, normalTop, textureBottomLeft);
vertices[13] = new VertexPositionNormalTexture(topRightBack, normalTop, textureTopRight);
vertices[14] = new VertexPositionNormalTexture(topLeftBack, normalTop, textureTopLeft);
vertices[15] = new VertexPositionNormalTexture(topLeftFront, normalTop, textureBottomLeft);
vertices[16] = new VertexPositionNormalTexture(topRightFront, normalTop, textureBottomRight);
vertices[17] = new VertexPositionNormalTexture(topRightBack, normalTop, textureTopRight);
//BOTTOM face.
vertices[18] = new VertexPositionNormalTexture(btmLeftFront, normalBottom, textureTopLeft);
vertices[19] = new VertexPositionNormalTexture(btmLeftBack, normalBottom, textureBottomLeft);
vertices[20] = new VertexPositionNormalTexture(btmRightBack, normalBottom, textureBottomRight);
vertices[21] = new VertexPositionNormalTexture(btmLeftFront, normalBottom, textureTopLeft);
vertices[22] = new VertexPositionNormalTexture(btmRightBack, normalBottom, textureBottomRight);
vertices[23] = new VertexPositionNormalTexture(btmRightFront, normalBottom, textureTopRight);
//LEFT face.
vertices[24] = new VertexPositionNormalTexture(topLeftFront, normalLeft, textureTopRight);
vertices[25] = new VertexPositionNormalTexture(btmLeftBack, normalLeft, textureBottomLeft);
vertices[26] = new VertexPositionNormalTexture(btmLeftFront, normalLeft, textureBottomRight);
vertices[27] = new VertexPositionNormalTexture(topLeftBack, normalLeft, textureTopLeft);
vertices[28] = new VertexPositionNormalTexture(btmLeftBack, normalLeft, textureBottomLeft);
vertices[29] = new VertexPositionNormalTexture(topLeftFront, normalLeft, textureTopRight);
//RIGHT face.
vertices[30] = new VertexPositionNormalTexture(topRightFront, normalRight, textureTopLeft);
vertices[31] = new VertexPositionNormalTexture(btmRightFront, normalRight, textureBottomLeft);
vertices[32] = new VertexPositionNormalTexture(btmRightBack, normalRight, textureBottomRight);
vertices[33] = new VertexPositionNormalTexture(topRightBack, normalRight, textureTopRight);
vertices[34] = new VertexPositionNormalTexture(topRightFront, normalRight, textureTopLeft);
vertices[35] = new VertexPositionNormalTexture(btmRightBack, normalRight, textureBottomRight);
blocks.Add(vertices);
}
}
public override void Draw(GameTime gameTime)
{
radians+=0.01f;
Vector3 camPos = new Vector3(0, -14.1759f, 10f);
Vector3 lookAt = new Vector3(0, 0, 0);
var view = Matrix.CreateRotationZ(MathHelper.ToRadians(45f)) * Matrix.CreateLookAt(camPos, lookAt, Vector3.Up);
// view *= Matrix.CreateRotationY(radians);
effect.Parameters["ViewMatrix"].SetValue(view);
foreach (var pass in effect.CurrentTechnique.Passes)
{
effect.Parameters["ModelTexture"].SetValue(checkerboardTexture2);
pass.Apply();
for (int i = 0; i < blocks.Count; i++)
{
graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, blocks[i], 0, blocks[i].Length / 3);
}
}
结果
然后旋转视图矩阵,这些法线看起来很好。
似乎您没有启用backface culling。我还没有使用过MonoGame,但是根据一些谷歌搜索,应该是这样的:
RasterizerState rs = new RasterizerState();
rs.CullMode = CullMode.CullClockwiseFace;