C#SharpDX如何正确设置纹理坐标?

时间:2017-05-29 10:51:36

标签: c# sharpdx direct3d11

我正在尝试在立方体上渲染纹理。但是,我做错了什么。我有纹理,但坐标看起来像错了,我不知道如何正确设置它。我错过了什么?我想我必须对IndexBuffer和UV做点什么。但是,我的思绪非常复杂。

我得到的结果:https://www.youtube.com/watch?v=_fdJAaU81sQ

Mesh.cs

ComboBoxes

Program.cs的

 public class Mesh : IDisposable
    {
        public string File;
        public string Name;
        public Vector4[] Vertices { get; set; }
        public int VerticesCount=0;
        public Vector3 Position; //BASED ON PIVOT
        public Vector3 PivotPosition; //MOVE MESH BASED ON THIS POSITION
        public Vector3 Rotation;
        public double Weight;
        public SharpDX.Direct3D11.Device d3dDevice;
        public SharpDX.Direct3D11.Buffer VerticesBuffer;

        public bool IsDisposed=false;
        public bool IsSelected = false;
        public int Triangles;
        public string Texture_DiffuseMap;                

        public Mesh(string _name, Vector4[] _vertices, string _file, SharpDX.Direct3D11.Device _device, string _Texture_DiffuseMap = "")
        {
            Vertices = new[]
            {
                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
                new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
                new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
                new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
                new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
                new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
                new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
                new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
                new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
                new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
                new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
                new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
                new Vector4(-1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
                new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
                new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
                new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
                new Vector4( 1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
                new Vector4(-1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
                new Vector4( 1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
                new Vector4(-1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
                new Vector4(-1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
                new Vector4( 1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
                new Vector4( 1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
                new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
                new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
                new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
                new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
                new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
                new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
                new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
                new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
                new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
                new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
            };
            Texture_DiffuseMap = _Texture_DiffuseMap;
            _vertices = Vertices;
            d3dDevice = _device;
            VerticesCount = Vertices.Count();

            Name = _name;
            File = _file;
            Meshes.Add(this);
        }

        // Other functions go here...

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
            IsDisposed = true;

        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                Dispose();
            }
            // free native resources if there are any.
            VerticesBuffer.Dispose();
            IsDisposed = true;
        }

        public void Render()
        {

            d3dDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            d3dDevice.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VerticesBuffer, Utilities.SizeOf<Vector4>() * 2, 0));


            d3dDevice.ImmediateContext.Draw(VerticesCount,0);


            /*d3dDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList;

            d3dDevice.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VerticesBuffer, Utilities.SizeOf<Vector4>() * 2, 0));

            d3dDevice.ImmediateContext.Draw(VerticesCount, 0);
            */
            VerticesBuffer.Dispose();
        }
    }

MiniCube.hlsl

            [STAThread]
    private static void Main()
    {
        new Thread(new ThreadStart(() =>
        {
            DisposeCollector DC=new DisposeCollector();
            var form = new RenderForm(Globals.Window_Title) { Width = Globals.Window_Size.Width, Height = Globals.Window_Size.Height, AllowUserResizing = false, MinimizeBox = false };
            InputHandler IHandler = new InputHandler(form);
            SampleDescription SamplerDesc = new SampleDescription(8, 0);
            // SwapChain description
            var desc = new SwapChainDescription()
            {
                BufferCount = 2,
                ModeDescription = new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed = true,
                OutputHandle = form.Handle,
                SampleDescription = SamplerDesc,
                SwapEffect = SwapEffect.Discard,
                Usage = Usage.RenderTargetOutput
            };

            var samplerStateDescription = new SamplerStateDescription
            {
                AddressU = TextureAddressMode.Wrap,
                AddressV = TextureAddressMode.Wrap,
                AddressW = TextureAddressMode.Wrap,
                Filter = Filter.MinMagMipLinear
            };
            var rasterizerStateDescription = RasterizerStateDescription.Default();
            rasterizerStateDescription.IsFrontCounterClockwise = true;

            // Used for debugging dispose object references
            Configuration.EnableObjectTracking = true;

            // Disable throws on shader compilation errors
            Configuration.ThrowOnShaderCompileError = false;

            SharpDX.DXGI.Factory factory = new SharpDX.DXGI.Factory1();
            SharpDX.DXGI.Adapter adapter = factory.GetAdapter(1);

            Adapter[] availableAdapters = factory.Adapters;
            foreach(Adapter _adapter in availableAdapters)
            {
                Console.WriteLine(_adapter.Description.Description);
            }
            // Create Device and SwapChain
            Device device;
            SwapChain swapChain;
            Device.CreateWithSwapChain(adapter, DeviceCreationFlags.SingleThreaded, desc, out device, out swapChain);

            var context = device.ImmediateContext;

            //factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);

            // Compile Vertex and Pixel shaders
            var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.hlsl", "VS", "vs_5_0", ShaderFlags.Debug);
            var vertexShader = new VertexShader(device, vertexShaderByteCode);

            var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.hlsl", "PS", "ps_5_0", ShaderFlags.Debug);
            var pixelShader = new PixelShader(device, pixelShaderByteCode);

            var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);

            // Layout from VertexShader input signature
            var layout = new InputLayout(device, signature, new[]
            {
            new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
            new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 0, 0),
            new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0),
            new InputElement("TEXCOORD", 0, Format.R32G32_Float, InputElement.AppendAligned, 0)

            });

            var samplerState = new SamplerState(device, samplerStateDescription);

            Mesh mesh1 = new Mesh("mesh1", new[] { new Vector4(0, 0, 0, 1) }, "", device, "1_Purple.jpg") { IsSelected=true };
            Mesh mesh2 = new Mesh("mesh2", new[] { new Vector4(0, 0, 0, 1) }, "", device, "1_GREEN.jpg");
            //MenuCreator menu1 = new MenuCreator(device,new[] {new Vector4(0, 0, 0, 0) });
            // Create Constant Buffer
            var contantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

            ShaderResourceView textureView;
            SharpDX.WIC.ImagingFactory2 ImagingFactory2 = new SharpDX.WIC.ImagingFactory2();

            // Prepare All the stages
            context.InputAssembler.InputLayout = layout;


            context.VertexShader.SetConstantBuffer(0, contantBuffer);
            context.VertexShader.Set(vertexShader);
            context.PixelShader.Set(pixelShader);
            context.PixelShader.SetSampler(0, samplerState);
            //context.PixelShader.SetShaderResource(0, textureView);

            Matrix proj = Matrix.Identity;

            // Use clock
            var clock = new Stopwatch();
            FPS fps = new FPS();
            clock.Start();

            // Declare texture for rendering
            bool userResized = true;
            Texture2D backBuffer = null;
            RenderTargetView renderView = null;
            Texture2D depthBuffer = null;
            DepthStencilView depthView = null;

            // Setup handler on resize form
            form.UserResized += (sender, args) => userResized = true;

            // Setup full screen mode change F5 (Full) F4 (Window)
            form.KeyUp += (sender, args) =>
            {
                if (args.KeyCode == Keys.F5)
                swapChain.SetFullscreenState(true, null);
                else if (args.KeyCode == Keys.F4)
                    swapChain.SetFullscreenState(false, null);
                else if (args.KeyCode == Keys.Escape)
                    form.Close();
            };

            //CREATE DEPTH STENCIL DESCRIPTION
            DepthStencilStateDescription depthSSD = new DepthStencilStateDescription();
            depthSSD.IsDepthEnabled = false;
            depthSSD.DepthComparison = Comparison.LessEqual;
            depthSSD.DepthWriteMask = DepthWriteMask.Zero;
            DepthStencilState DSState = new DepthStencilState(device, depthSSD);

            Camera camera = new Camera();
            camera.eye = new Vector3(0, 0, -5);
            camera.target = new Vector3(0, 0, 0);
            Globals.Render = true;
            /*void DrawEmptyCircle(Vector3 startPoint, Vector2 radius, Color color)
            {
                List<VertexPositionColor> circle = new List<VertexPositionColor>();
                float X, Y;

                var stepDegree = 0.3f;
                for (float angle = 0; angle <= 360; angle += stepDegree)
                {
                    X = startPoint.X + radius.X * (float)Math.Cos((angle));
                    Y = startPoint.Y + radius.Y * (float)Math.Sin((angle));
                    Vector3 point = new Vector3(X, Y, 0);
                    circle.Add(new VertexPositionColor(point, color));
                }
            }*/
            CubeApp.Windows.SystemInformation.Print(CubeApp.Windows.SystemInformation.GetSystemInformation());
            HardwareInformation.GetHardwareInformation("Win32_DisplayConfiguration", "Description");

            // Main loop
            RenderLoop.Run(form, () =>
            {


                    fps.Count();fps.setFormHeader(form);
                // Prepare matrices
                if (Globals.Render)
                {
                    var view = camera.getView();

                // If Form resized
                if (userResized)
                {
                    // Dispose all previous allocated resources
                    Utilities.Dispose(ref backBuffer);
                    Utilities.Dispose(ref renderView);
                    Utilities.Dispose(ref depthBuffer);
                    Utilities.Dispose(ref depthView);

                        foreach (Mesh _mesh in Meshes.MeshCollection)
                    {
                        if (_mesh.IsDisposed == false)
                        {
                            Utilities.Dispose(ref _mesh.VerticesBuffer);
                        }
                    }

                        // Resize the backbuffer
                        swapChain.ResizeBuffers(desc.BufferCount, form.ClientSize.Width, form.ClientSize.Height, Format.Unknown, SwapChainFlags.None);
                        // Get the backbuffer from the swapchain
                        backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
                        // Renderview on the backbuffer
                        renderView = new RenderTargetView(device, backBuffer);
                        // Create the depth buffer
                        depthBuffer = new Texture2D(device, new Texture2DDescription()
                        {
                            Format = Format.D32_Float_S8X24_UInt,
                            ArraySize = 1,
                            MipLevels = 1,
                            Width = form.ClientSize.Width,
                            Height = form.ClientSize.Height,
                            SampleDescription = SamplerDesc,
                            Usage = ResourceUsage.Default,
                            BindFlags = BindFlags.DepthStencil,
                            CpuAccessFlags = CpuAccessFlags.None,
                            OptionFlags = ResourceOptionFlags.None
                        });

                        // Create the depth buffer view
                        depthView = new DepthStencilView(device, depthBuffer);
                        // Setup targets and viewport for rendering
                        context.Rasterizer.SetViewport(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
                        //context.OutputMerger.SetDepthStencilState(DSState);
                        context.OutputMerger.SetTargets(depthView, renderView);
                        // Setup new projection matrix with correct aspect ratio
                        proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, form.ClientSize.Width / (float)form.ClientSize.Height, 0.1f, 100.0f);
                        // We are done resizing
                        userResized = false;
                    }
                    var time = clock.ElapsedMilliseconds / 1000.0f;
                    var viewProj = Matrix.Multiply(view, proj);

            // Clear views
            context.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
            context.ClearRenderTargetView(renderView, Color.WhiteSmoke);

            // Update WorldViewProj Matrix
            var worldViewProj = Matrix.RotationX(45) * Matrix.RotationY(0 * 2) * Matrix.RotationZ(0 * .7f) * viewProj;
            worldViewProj.Transpose();
            context.UpdateSubresource(ref worldViewProj, contantBuffer);

                //Update Camera Position
                Vector3 _camEye = camera.eye;
                Vector3 _camTarget = camera.target;

                if (IHandler.KeyW)
                {
                    _camEye.Z+= 0.050f; _camTarget.Z += 0.050f;
                }
                if (IHandler.KeyS)
                {
                    _camEye.Z -= 0.050f; _camTarget.Z -= 0.050f;
                }
                if (IHandler.KeyA)
                {
                        _camEye.X -= 0.050f; _camTarget.X -= 0.050f;

                }
                if (IHandler.KeyD)
                {
                    _camTarget.X += 0.050f;
                    _camEye.X += 0.050f;

                }
                if (IHandler.KeyQ)
                {

                }
                camera.eye = _camEye;
                camera.target = _camTarget;
                camera.updateView();

                // Draw the cube
                foreach (Mesh __mesh in Meshes.MeshCollection)
                {
                    if ( __mesh.IsSelected )
                    {
                        for (int i = 0; i <= __mesh.VerticesCount - 1; i++)
                        {
                            if (IHandler.KeyRight) __mesh.Vertices[i].X += 0.050f;
                            if (IHandler.KeyLeft) __mesh.Vertices[i].X -= 0.050f;
                            if (IHandler.KeyUp) __mesh.Vertices[i].Y += 0.050f;
                            if (IHandler.KeyDown) __mesh.Vertices[i].Y -= 0.050f;
                        }
                }
                        var texture = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(ImagingFactory2, __mesh.Texture_DiffuseMap));
                        textureView = new ShaderResourceView(device, texture);

                        context.PixelShader.SetShaderResource(0, textureView);
                        texture.Dispose();
                        textureView.Dispose();
                        __mesh.VerticesBuffer = SharpDX.Direct3D11.Buffer.Create(device, BindFlags.VertexBuffer, __mesh.Vertices);
                    //EnvironmentDisplayModes.SetDisplayMode(device, __mesh, EnvironmentDisplayModes.DisplayMode.Standart);
                    __mesh.Render();
            }

            // Present!
            swapChain.Present(0, PresentFlags.None);
                }
            });
            // Release all resources
            foreach (Mesh msh in Meshes.MeshCollection)
            {
                msh.d3dDevice.Dispose();
                msh.VerticesBuffer.Dispose();
            }
        DC.DisposeAndClear();
        signature.Dispose();
        vertexShaderByteCode.Dispose();
        vertexShader.Dispose();
        pixelShaderByteCode.Dispose();
        pixelShader.Dispose();
        layout.Dispose();
        contantBuffer.Dispose();
        depthBuffer.Dispose();
        depthView.Dispose();
        renderView.Dispose();
        backBuffer.Dispose();
        ImagingFactory2.Dispose();
        device.Dispose();
        context.Dispose();
        swapChain.Dispose();
        factory.Dispose();
        adapter.Dispose();
        DSState.Dispose();
        samplerState.Dispose();
        DC.Dispose();
        form.Dispose();
        })).Start();   
}
}

1 个答案:

答案 0 :(得分:0)

首先,将纹理坐标存储在顶点中是很常见的。 因此,首先要做的就是将顶点的结构更改为:

public MyVertex
{ 
     public Vector3 Position;
     public Vector3 Normal;
     public Vector2 TextureCoord;
}

我认为没有必要使位置和法线成为vector4,所以这应该这样做。当您使用纹理时,也不需要在顶点结构中使用颜色。

接下来,将着色器的输入结构更改为上述结构。在着色器中,也在你的初始化中。

建议您在网格初始化中设置纹理坐标。一个例子是飞机:

var vertices = new MyVertex[] { new MyVertex(){Position = new Vector3(0.0f, 0.0f, 0.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(0.0f, 0.0f)}, new MyVertex(){Position = new Vector3(1.0f, 0.0f, 0.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(1.0f, 0.0f)}, new MyVertex(){Position = new Vector3(1.0f, 0.0f, 1.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(1.0f, 1.0f)}, new MyVertex(){Position = new Vector3(0.0f, 0.0f, 1.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(0.0f, 1.0f)} };

如果你存储这样的顶点,它应该像魅力一样工作。 剩下要做的就是使用输入texturecoordinates来为着色器中传递的纹理进行采样。

如果你想使用简单的纹理映射,也不需要在着色器中操作texturecoordinates。否则,您可以在维基百科上查找不同类型的纹理映射,如球形,盒形或平面纹理映射。