问题描述:

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();

}

}

}

网友答案:

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.

网友答案:

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);
});
相关阅读:
Top