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:
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.