使用SlimDX时剪辑和3D投影不正确

我正在开发一个简单的项目,我希望使用SlimDX在WinForms应用程序中显示一个3D对象。 我已经创建了一个小项目,但我遇到的问题是我渲染的对象被剪切在0.0f和-1.0f之间。

我看了一个朋友的类似项目的代码(他们没有这个问题),并且无法弄清楚它为什么会发生。 我必须将对象的大小限制在-0.1f – > 0.1f的范围内,以便我能够看到它。 延伸我的远程飞机什么也没做。 我朋友正在使用的项目可以加载超过我的500倍的对象,没有剪切问题。

有没有人有什么建议? (请参阅下面的屏幕截图和代码)

屏幕截图

表格代码

namespace TestOfTheTest { using System.Drawing; using System.Windows.Forms; using SlimDX; using SlimDX.Direct3D9; using MathHelper = Microsoft.Xna.Framework.MathHelper; public struct VertexPositionColor { private static VertexDeclaration sDeclaration; public static VertexElement[] Elements = { new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), new VertexElement(0, sizeof(float) * 3, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.Color, 0), VertexElement.VertexDeclarationEnd }; public Vector3 Position; public Color4 Color; public VertexPositionColor(Vector3 position, Color4 color) { this.Position = position; this.Color = color; } public static int DeclarationSize { get { return (sizeof(float) * 3) + (sizeof(float) * 4); } } public static VertexDeclaration GetDeclaration(Device device) { if (sDeclaration == null) { sDeclaration = new VertexDeclaration(device, Elements); } return sDeclaration; } } public partial class Form1 : Form { private Device mDevice; private VertexPositionColor[] mVertices; private VertexBuffer mVertexBuffer; private VertexShader mVertexShader; private PixelShader mPixelShader; private Point? mLastPosition = null; private float mAngle = 0.0f; public Form1() { InitializeComponent(); this.Load += Form1_Load; this.RenderSurface.MouseDown += RenderSurface_MouseDown; this.RenderSurface.MouseMove += RenderSurface_MouseMove; this.RenderSurface.MouseUp += RenderSurface_MouseUp; } #region UI Event Handlers private void Form1_Load(object sender, System.EventArgs e) { var parameters = new PresentParameters() { BackBufferWidth = this.RenderSurface.Width, BackBufferHeight = this.RenderSurface.Height, Windowed = true, DeviceWindowHandle = this.RenderSurface.Handle }; mDevice = new Device(new Direct3D(), 0, DeviceType.Hardware, this.RenderSurface.Handle, CreateFlags.HardwareVertexProcessing, parameters); // Create the vertices mVertices = new VertexPositionColor[3]; mVertices[0].Position = new Vector3(-0.1f, -0.1f, -1.0f); mVertices[0].Color = new Color4(1.0f, 1.0f, 0.0f, 0.0f); mVertices[1].Position = new Vector3(0.0f, 0.1f, -1.0f); mVertices[1].Color = new Color4(1.0f, 0.0f, 1.0f, 0.0f); mVertices[2].Position = new Vector3(0.1f, -0.1f, -1.0f); mVertices[2].Color = new Color4(1.0f, 0.0f, 0.0f, 1.0f); // Fill the vertex buffer mVertexBuffer = new VertexBuffer(mDevice, VertexPositionColor.DeclarationSize, Usage.WriteOnly, VertexFormat.Position, Pool.Default); mVertexBuffer.Lock(0, VertexPositionColor.DeclarationSize * mVertices.Length, LockFlags.None).WriteRange(mVertices); mVertexBuffer.Unlock(); // Load the shaders var vsByteCode = ShaderBytecode.CompileFromFile(@"\Shaders\DefaultShader.vs.hlsl", "DefaultVertexShader", "vs_2_0", ShaderFlags.None); var psByteCode = ShaderBytecode.CompileFromFile(@"\Shaders\DefaultShader.ps.hlsl", "DefaultPixelShader", "ps_2_0", ShaderFlags.None); mVertexShader = new VertexShader(mDevice, vsByteCode); mPixelShader = new PixelShader(mDevice, psByteCode); // Setup render states mDevice.SetRenderState(RenderState.CullMode, Cull.None); } private void RenderSurface_MouseDown(object sender, MouseEventArgs e) { mLastPosition = e.Location; } private void RenderSurface_MouseMove(object sender, MouseEventArgs e) { if (mLastPosition == null) { return; } var position = e.Location; var lastPosition = mLastPosition.Value; mAngle += ((position.X - lastPosition.X) / 20.0f); mLastPosition = position; } private void RenderSurface_MouseUp(object sender, MouseEventArgs e) { mLastPosition = null; } #endregion #region Rendering public void MainLoop() { var device = mDevice; // Calculate matrices Matrix projection = Matrix.PerspectiveFovRH(MathHelper.PiOver4, (float)this.RenderSurface.Width / (float)this.RenderSurface.Height, 1.0f, 1000.0f); Matrix view = Matrix.LookAtRH(Vector3.UnitZ, Vector3.Zero, Vector3.UnitY) * Matrix.RotationY(mAngle); Matrix viewProjection = view * projection; // Initialize the graphics device device.VertexShader = mVertexShader; device.PixelShader = mPixelShader; device.SetVertexShaderConstant(0, viewProjection); // Render the scene device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, unchecked((int)0x00000000), 1.0f, 0); device.BeginScene(); device.VertexDeclaration = VertexPositionColor.GetDeclaration(device); device.SetStreamSource(0, mVertexBuffer, 0, VertexPositionColor.DeclarationSize); device.DrawPrimitives(PrimitiveType.TriangleList, 0, mVertices.Length); device.EndScene(); device.Present(); } #endregion } } 

顶点着色器代码

 float4x4 mWorldViewProjection; struct VertexShaderInput { float4 Position : POSITION; float4 Color : COLOR; }; struct VertexShaderOutput { float4 Position : POSITION0; float4 Color : TEXCOORD0; }; VertexShaderOutput DefaultVertexShader ( VertexShaderInput input ) { VertexShaderOutput output = ( VertexShaderOutput ) 0; // Transform coordinates output.Position = mul(input.Position, mWorldViewProjection); // Copy other values output.Color = input.Color; return output; } 

像素着色器代码

 struct PixelShaderInput { float4 Color : TEXCOORD0; }; float4 DefaultPixelShader ( PixelShaderInput input ) : COLOR0 { return input.Color; } 

我找到了解决方案。 基本上,当在DirectX(或在本例中为SlimDX)中单独使用顶点和像素着色器并使用SetVertexShaderConstant函数将矩阵传递到顶点着色器时,这些矩阵被转置并存储为行主矩阵,而不是列 -重大的。

有两种方法可以解决这个问题。

  1. 在使用图形设备上的SetVertexShaderConstant函数将所有矩阵传递到顶点着色器之前预转置所有矩阵。
  2. 利用DirectX效果框架,它自己处理这个预转换,使得更容易使用矩阵。

可以在此处找到导致分辨率的这种差异的指示。