Incorrect Clipping and 3D Projection when using SlimDX

♀尐吖头ヾ 提交于 2019-12-10 18:59:05

问题


I am working on a simple project whereby I wish to display a 3D object within a WinForms application using SlimDX. I have created a small project to do this, but I am encountering a problem where the object I have rendered is being clipped between 0.0f and -1.0f.

I have looked at a friend's code for a similar project (they do not have this problem) and cannot work out why it is happening. I've had to restrict the size of my object to the range of -0.1f -> 0.1f in order for me to be able to see it. Extending my far plane does nothing. The project my friend is using can load objects over 500 times the size of mine, with no clipping issues.

Does anyone have any suggestions? (Please see below for the screen shots and code)

Form Code

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

Vertex Shader Code

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 Code

struct PixelShaderInput
{
    float4 Color : TEXCOORD0;
};

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

回答1:


I found the solution. Basically, when using the Vertex and Pixel Shaders separately in DirectX (or in this case, SlimDX) and using the SetVertexShaderConstant function to pass the matrices to the vertex shader, those matrices are transposed and stored as row-major matrices, instead of column-major.

There are two ways of resolving this.

  1. Pre-transpose all matrices before passing them to the vertex shader using the SetVertexShaderConstant function on the graphics device.
  2. Make use of the DirectX Effect framework, which handles this pre-transposition itself, making it easier to work with the matrices.

Indication of this difference that lead to the resolution can be found here.



来源:https://stackoverflow.com/questions/7739442/incorrect-clipping-and-3d-projection-when-using-slimdx

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!