Question

OK - I'm a complete newbie to SlimDX, DirectX and graphics programming in general and I need to get up to speed.

I'm attempting to develop a prototyping app to visualize and debug data that I will eventually be using n a non-graphical application.

I've worked my way through the three SlimDX tutorials and I'm starting to get a grasp on the approaches used however I've hit a roadblock because I can't figure out how to draw more than one object.....

The SimpleTriangle sample shows how to draw a single triangle. I'm trying to extend that sample to draw two triangles. I'm not interested in using instances etc. at this time because in general the objects in my application will all be different - I'm just using two triangles here because it was easy to modify the existing vertex data....

I've included the modified source of the sample here, and I'm hoping that someone can help me get past this basic roadblock.

What i have done is,

1) Create a second array of vertex data that (offsets the first triangle one unit along the x axis) 2) Create a second Buffer and fill it with the vertex data from my new array 3) Create VertexBufferBindings that bind the Vertex Arrays 4) Put the two VertexBufferBdings in into an array 5) Send the array of VertexBufferBinding to the Input Assembler 6) Draw

What I get on the screen is just the first triangle. If I switch the order of the triangles I do see the offset triangle. i just can't see both at the same time....

Here's the code.

I'd be very grateful for any help with this.....

Doug

using System.Windows.Forms;
using SlimDX;
using SlimDX.D3DCompiler;
using SlimDX.Direct3D11;
using SlimDX.DXGI;
using SlimDX.Windows;
using Device = SlimDX.Direct3D11.Device;
using Resource = SlimDX.Direct3D11.Resource;

namespace SimpleTriangle
{
    static class Program
    {
        static void Main()
        {
            Device device;
            SwapChain swapChain;
            ShaderSignature inputSignature;
            VertexShader vertexShader;
            PixelShader pixelShader;

            var form = new RenderForm("Tutorial 3: Simple Triangle");
            var description = new SwapChainDescription()
            {
                BufferCount = 2,
                Usage = Usage.RenderTargetOutput,
                OutputHandle = form.Handle,
                IsWindowed = true,
                ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                SampleDescription = new SampleDescription(1, 0),
                Flags = SwapChainFlags.AllowModeSwitch,
                SwapEffect = SwapEffect.Discard
            };

            Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, description, out device, out swapChain);

            // create a view of our render target, which is the backbuffer of the swap chain we just created
            RenderTargetView renderTarget;
            using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
                renderTarget = new RenderTargetView(device, resource);

            // setting a viewport is required if you want to actually see anything
            var context = device.ImmediateContext;
            var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height);
            context.OutputMerger.SetTargets(renderTarget);
            context.Rasterizer.SetViewports(viewport);

            // load and compile the vertex shader
            using (var bytecode = ShaderBytecode.CompileFromFile("triangle.fx", "VShader", "vs_4_0", ShaderFlags.None, EffectFlags.None))
            {
                inputSignature = ShaderSignature.GetInputSignature(bytecode);
                vertexShader = new VertexShader(device, bytecode);
            }

            // load and compile the pixel shader
            using (var bytecode = ShaderBytecode.CompileFromFile("triangle.fx", "PShader", "ps_4_0", ShaderFlags.None, EffectFlags.None))
                pixelShader = new PixelShader(device, bytecode);

            // create test vertex data, making sure to rewind the stream afterward
            var vertices = new DataStream(12 * 3, true, true);
            vertices.Write(new Vector3(0.0f, 0.5f, 0.5f));
            vertices.Write(new Vector3(0.5f, -0.5f, 0.5f));
            vertices.Write(new Vector3(-0.5f, -0.5f, 0.5f));
            vertices.Position = 0;


            //Create the second triangle - offset from the first
            var vertices2 = new DataStream(12 * 3, true, true);
            vertices2.Write(new Vector3(1.0f, 0.5f, 0.5f));
            vertices2.Write(new Vector3(1.5f, -0.5f, 0.5f));
            vertices2.Write(new Vector3(0.5f, -0.5f, 0.5f));
            vertices2.Position = 0;

            // create the vertex layout
            var elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0) };
            var layout = new InputLayout(device, inputSignature, elements);

            // Create the vertex buffers
            var vertexBuffer = new Buffer(device, vertices, 12 * 3, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            var vertexBuffer2 = new Buffer(device, vertices2, 12 * 3, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

            // Bind the vertex buffer
            var vertexBufferBindings = new VertexBufferBinding[2];
            vertexBufferBindings[0] = new VertexBufferBinding(vertexBuffer, 12, 0);
            vertexBufferBindings[1] = new VertexBufferBinding(vertexBuffer2, 12, 0);

            // configure the Input Assembler portion of the pipeline with the vertex data
            context.InputAssembler.InputLayout = layout;
            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            context.InputAssembler.SetVertexBuffers(0, vertexBufferBindings);

            // set the shaders
            context.VertexShader.Set(vertexShader);
            context.PixelShader.Set(pixelShader);

            // prevent DXGI handling of alt+enter, which doesn't work properly with Winforms
            using (var factory = swapChain.GetParent<Factory>())
                factory.SetWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAltEnter);

            // handle alt+enter ourselves
            form.KeyDown += (o, e) =>
            {
                if (e.Alt && e.KeyCode == Keys.Enter)
                    swapChain.IsFullScreen = !swapChain.IsFullScreen;
            };

            // handle form size changes
            form.UserResized += (o, e) =>
            {
                renderTarget.Dispose();

                swapChain.ResizeBuffers(2, 0, 0, Format.R8G8B8A8_UNorm, SwapChainFlags.AllowModeSwitch);
                using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
                    renderTarget = new RenderTargetView(device, resource);

                context.OutputMerger.SetTargets(renderTarget);
            };

            MessagePump.Run(form, () =>
            {
                // clear the render target to a soothing blue
                context.ClearRenderTargetView(renderTarget, new Color4(0.5f, 0.5f, 1.0f));

                // draw the triangle              
                context.Draw(3, 0);

                swapChain.Present(0, PresentFlags.None);
            });

            // clean up all resources
            // anything we missed will show up in the debug output
            vertices.Close();
            vertices2.Close();
            vertexBuffer.Dispose();
            layout.Dispose();
            inputSignature.Dispose();
            vertexShader.Dispose();
            pixelShader.Dispose();
            renderTarget.Dispose();
            swapChain.Dispose();
            device.Dispose();
        }
    }
}
Was it helpful?

Solution

You should set the vertex buffers independently from each other:

//initializing...
var vbb1 = new VertexBufferBinding[] { new VertexBufferBinding(vertexBuffer, 12, 0) };
var vbb2 = new VertexBufferBinding[] { new VertexBufferBinding(vertexBuffer2, 12, 0) };

//in the render loop
context.InputAssembler.SetVertexBuffers(0, vbb1);
context.Draw(3, 0);

context.InputAssembler.SetVertexBuffers(0, vbb2);
context.Draw(3, 0);

Binding two vertex buffers to the input assembler at the same time is used when you need the data from those buffers in one draw call. E.g. if you have position data in the one buffer and color data in the other.

OTHER TIPS

Although I don't use SlimDX, I do use DirectX and have done for some time. Looking at the tutorial, I would imagine that you would need to draw each vertex buffer separately.

So, something like this:

MessagePump.Run(form, () =>
{
    // clear the render target to a soothing blue
    context.ClearRenderTargetView(renderTarget, new Color4(0.5f, 0.5f, 1.0f));

    // draw the first triangle              
    context.InputAssembler.SetVertexBuffers(0, vertexBufferBindings[0]);
    context.Draw(3, 0);

    // draw the second triangle              
    context.InputAssembler.SetVertexBuffers(0, vertexBufferBindings[1]);
    context.Draw(3, 0);

    swapChain.Present(0, PresentFlags.None);
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top