不正确裁剪和3D投影使用SlimDX时,不正确、SlimDX

2023-09-09 21:17:04 作者:烂人

我在一个简单的项目工作,由此我想在使用SlimDX一个WinForms应用程序中显示3D对象。我创建了一个小项目要做到这一点,但我遇到了在那里我有渲染对象被0.0和之间-1.0F裁剪的问题。

我已经看过朋友的$ C $下一个类似的项目(他们没有这个问题),不能工作了,为什么它正在发生。我不得不限制我的对象到-0.1f范围的大小 - > 0.1F为了让我能够看到它。延长我的远平面什么都不做。我的朋友正在使用可装载过我的500倍大小的物体的项目,没有裁剪的问题。

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

表code

 命名空间TestOfTheTest
{
    使用System.Drawing中;
    使用System.Windows.Forms的;
    使用SlimDX;
    使用SlimDX.Direct3D9;
    使用MathHelper = Microsoft.Xna.Framework.MathHelper;

    公共结构VertexPositionColor
    {
        私有静态VertexDeclaration sDeclaration;
        公共静态VertexElement []元素=
        {
            新VertexElement(0,0,DeclarationType.Float3,DeclarationMethod.Default,DeclarationUsage.Position,0),
            新VertexElement(0,sizeof的(浮动)* 3,DeclarationType.Float4,DeclarationMethod.Default,DeclarationUsage.Color,0),
            VertexElement.VertexDeclarationEnd
        };

        公共Vector3类型的位置;
        公共Color4颜色;

        公共VertexPositionColor(Vector3类型位置,Color4颜色)
        {
            this.Position =位置;
            this.Color =颜色;
        }

        公共静态INT DeclarationSize
        {
            {返回(的sizeof(浮动)* 3)+(的sizeof(浮动)* 4); }
        }

        公共静态VertexDeclaration GetDeclaration(设备装置)
        {
            如果(sDeclaration == NULL)
            {
                sDeclaration =新VertexDeclaration(设备,要素);
            }

            返回sDeclaration;
        }
    }

    公共部分类Form1中:形态
    {
        私有设备mDevice;

        私人VertexPositionColor [] mVertices;
        私人VertexBuffer mVertexBuffer;

        私人VertexShader mVertexShader;
        私人PixelShader mPixelShader;

        私人点? mLastPosition = NULL;
        私人浮动裂伤= 0.0;

        公共Form1中()
        {
            的InitializeComponent();

            this.Load + = Form1_Load的;
            this.RenderSurface.MouseDown + = RenderSurface_MouseDown;
            this.RenderSurface.MouseMove + = RenderSurface_MouseMove;
            this.RenderSurface.MouseUp + = RenderSurface_MouseUp;
        }

        #地区UI事件处理程序

        私人无效Form1_Load的(对象发件人,发送System.EventArgs)
        {
            VAR参数=新的presentParameters()
            {
                BackBufferWidth = this.RenderSurface.Width,
                BackBufferHeight = this.RenderSurface.Height,
                窗= TRUE,
                DeviceWindowHandle = this.RenderSurface.Handle
            };

            mDevice =新设备(新的Direct3D(),0,DeviceType.Hardware,this.RenderSurface.Handle,CreateFlags.HardwareVertexProcessing,参数);

            //创建顶点
            mVertices =新VertexPositionColor [3];

            mVertices [0] .Position =新的Vector3类型(-0.1f,-0.1f,-1.0F);
            mVertices [0]。颜色=新Color4(1.0F,1.0F,0.0,0.0);
            mVertices [1] .Position =新的Vector3类型(0.0,0.1F,-1.0F);
            mVertices [1]。颜色=新Color4(1.0F,0.0,1.0F,0.0);
            mVertices [2] .Position =新的Vector3类型(0.1F,-0.1f,-1.0F);
            mVertices [2]。颜色=新Color4(1.0F,0.0,0.0,1.0F);

            //填充顶点缓冲区
            mVertexBuffer =新的VertexBuffer(mDevice,VertexPositionColor.DeclarationSize,Usage.WriteOnly,VertexFormat.Position,Pool.Default);
            mVertexBuffer.Lock(0,VertexPositionColor.DeclarationSize * mVertices.Length,LockFlags.None).WriteRange(mVertices);
            mVertexBuffer.Unlock();

            //将着色器
            VAR vsByte code = ShaderByte code.CompileFromFile(@\着色器\ DefaultShader.vs.hlsl,DefaultVertexShader,vs_2_0,ShaderFlags.None);
            VAR psByte code = ShaderByte code.CompileFromFile(@\着色器\ DefaultShader.ps.hlsl,DefaultPixelShader,ps_2_0,ShaderFlags.None);

            mVertexShader =新的VertexShader(mDevice,vsByte code);
            mPixelShader =新PixelShader(mDevice,psByte code);

            //设置渲染状态
            mDevice.SetRenderState(RenderState.CullMode,Cull.None);
        }

        私人无效RenderSurface_MouseDown(对象发件人,发送MouseEventArgs E)
        {
            mLastPosition = e.Location;
        }

        私人无效RenderSurface_MouseMove(对象发件人,发送MouseEventArgs E)
        {
            如果(mLastPosition == NULL)
            {
                返回;
            }

            VAR位置= e.Location;
            VAR lastPosition = mLastPosition.Value;

            裂伤+ =((position.X  -  lastPosition.X)/ 20.0f);

            mLastPosition =位置;
        }

        私人无效RenderSurface_MouseUp(对象发件人,发送MouseEventArgs E)
        {
            mLastPosition = NULL;
        }

        #endregion

        #区域渲染

        公共无效的主循环()
        {
            无功装置= mDevice;

            //计算矩阵
            矩阵投影= Matrix.PerspectiveFovRH(MathHelper.PiOver4,(浮动)this.RenderSurface.Width /(浮点)this.RenderSurface.Height,1.0F,1000.0f);
            矩阵视图= Matrix.LookAtRH(Vector3.UnitZ,Vector3.Zero,Vector3.UnitY)* Matrix.RotationY(裂伤);
            矩阵viewProjection =视图*投影;

            //初始化图形设备
            device.VertexShader = mVertexShader;
            device.PixelShader = mPixelShader;

            device.SetVertexShaderConstant(0,viewProjection);

            //渲染场景
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,取消选中((INT)00000000),1.0F,0);
            device.BeginScene();

            device.VertexDeclaration = VertexPositionColor.GetDeclaration(设备);
            device.SetStreamSource(0,mVertexBuffer,0,VertexPositionColor.DeclarationSize);

            device.DrawPrimitives(PrimitiveType.TriangleList,0,mVertices.Length);

            device.EndScene();
            。设备present();
        }

        #endregion
    }
}
 

的Vertex Shader code

  float4x4 mWorldViewProjection;

结构VertexShaderInput
{
    的float4职位:职位;
    的float4颜色:颜色;
};

结构VertexShaderOutput
{
    的float4位置:POSITION0;
    的float4颜色:TEXCOORD0;
};

VertexShaderOutput DefaultVertexShader(VertexShaderInput输入)
{
    VertexShaderOutput输出=(VertexShaderOutput)0;

    //变换坐标
    output.Position = MUL(input.Position,mWorldViewProjection);

    //复制其他值
    output.Color = input.Color;

    返回输出;
}
 

的Pixel Shader code

 结构PixelShaderInput
{
    的float4颜色:TEXCOORD0;
};

的float4 DefaultPixelShader(PixelShaderInput输入):COLOR0
{
    返回input.Color;
}
 
拍摄出来的视频画面效果不佳,怎么裁剪画面大小

解决方案

我找到了解决办法。基本上,DirectX中分别使用顶点和像素着色器时(或在此情况下,SlimDX),使用的SetVertexShaderConstant函数矩阵传递到顶点着色器,这些基质的转和存储,而不是列的主要是行为主的矩阵。

有解决此两种方式。

$ P $使用的图形设备上的SetVertexShaderConstant功能将它们传递到顶点着色器之前对转所有矩阵。 请用DirectX效果框架,它可以处理这个pre换位本身,使其更容易与矩阵的工作。

这种差异的指示,导致分辨率可以找到这里。

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

解决方案

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.

Pre-transpose all matrices before passing them to the vertex shader using the SetVertexShaderConstant function on the graphics device. 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.

 
精彩推荐
图片推荐