2011-10-12 28 views
3

我正在處理一個簡單的項目,我希望在使用SlimDX的WinForms應用程序中顯示3D對象。我已經創建了一個小項目來做到這一點,但是我遇到了一個問題,我已經渲染的對象被剪裁在0.0f和-1.0f之間。使用SlimDX時不正確的剪切和3D投影

我看了一個朋友的代碼爲一個類似的項目(他們沒有這個問題),並不能解決它爲什麼發生。我不得不將我的對象的大小限制在-0.1f - > 0.1f的範圍內,以便我能夠看到它。擴展我的遠程飛機什麼都不做。我的朋友正在使用的項目可以加載超過我的規模500倍的對象,而不存在裁剪問題。

有沒有人有任何建議? (請參見下面的屏幕截圖和代碼)

Screen Shots

表單代碼

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; 
} 

的Pixel Shader代碼

struct PixelShaderInput 
{ 
    float4 Color : TEXCOORD0; 
}; 

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

回答

1

我找到了解決方案。基本上,在DirectX(或本例中爲SlimDX)中分別使用頂點和像素着色器,並使用SetVertexShaderConstant函數將矩陣傳遞給頂點着色器時,這些矩陣爲transposed,並存儲爲行主矩陣,而不是列 - 重大的。

有兩種解決方法。

  1. 在將圖形設備上的SetVertexShaderConstant函數傳遞給頂點着色器之前,對所有矩陣進行預先轉置。
  2. 利用DirectX Effect框架,它可以處理這個預轉換本身,使它更容易處理矩陣。

指示導致分辨率的這種差異可以發現here