Lors de ma session aux TechDays 2008, j'ai animé une session sur DirectX10 et .Net.
Or, lors d'une démo j'ai écris le code nécessaire à l'affichage d'un triangle 2D rouge sur un fond bleu.
Sauf que la démo a surtout affiché le fond bleu :).
La raison était toute simple : j'avais oublié de définir le viewport!!!
Les pixels étaient envoyés à l'écran entre (-1.0, -1.0) et (1.0, 1.0). Voila tout!!
Grâce au viewport, ils seront envoyés entre (0, 0) et (1024, 768).
Le code final donne donc ça (le projet complet est dispo ici) :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SlimDX.Direct3D10;
using SlimDX;
using SlimDX.Direct3D;
using System.IO;
public partial class Form1 : Form
{
Device device;
SwapChain swapChain;
RenderTargetView view;
SlimDX.Direct3D10.Buffer vertexBuffer;
Effect effect;
EffectTechnique technique;
EffectPass pass;
InputLayout layout;
Viewport viewport = new Viewport();
RasterizerState state;
public Form1()
{
InitializeComponent();
}
private void cmdInitDevice_Click(object sender, EventArgs e)
{
// Device
device = new Device(DriverType.Hardware, DeviceCreationFlags.Debug);
CreateSwapChain();
// Effect
string err;
effect = Effect.FromFile(device, "MyEffect.fx", "fx_4_0", out err);
technique = effect.GetTechniqueByIndex(0);
pass = technique.GetPassByIndex(0);
InputElement[] elements = new InputElement[]
{
new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0,
InputClassification.PerVertexData, 0),
};
layout = new InputLayout(device, elements, pass.Signature);
}
private void CreateSwapChain()
{
if (swapChain != null)
{
swapChain.Dispose();
swapChain = null;
}
// Swap chain
SwapChainDescription description = new SwapChainDescription();
description.BufferCount = 1;
description.Flags = SwapChainFlags.None;
description.Format = Format.R8G8B8A8_UNorm;
description.Height = panel1.Height;
description.Width = panel1.Width;
description.Windowed = true;
description.RefreshRate = new Rational(60, 1);
description.SampleCount = 1;
description.SampleQuality = 0;
description.Scaling = DisplayModeScaling.Unspecified;
description.ScanlineOrdering = DisplayModeScanlineOrdering.Unspecified;
description.Usage = SurfaceUsage.RenderTargetOutput;
description.SwapEffect = SwapEffect.Discard;
description.OutputHandle = panel1.Handle;
swapChain = new SwapChain(device, description);
using (Texture2D backBuffer = swapChain.GetBuffer(0))
{
view = new RenderTargetView(device, backBuffer);
device.OutputMerger.SetTargets(view);
}
// Viewport
viewport.X = panel1.ClientRectangle.Left;
viewport.Y = panel1.ClientRectangle.Top;
viewport.Width = panel1.ClientSize.Width;
viewport.Height = panel1.ClientSize.Height;
viewport.MinZ = 0.0f;
viewport.MaxZ = 1.0f;
device.Rasterizer.SetViewports(viewport);
// States
RasterizerStateDescription desc = new RasterizerStateDescription();
desc.CullMode = CullMode.None;
state = new RasterizerState(device, desc);
}
internal void Render()
{
if (view != null)
{
view.Clear(new SlimDX.Direct3D.ColorValue(0, 0, 1.0f));
if (vertexBuffer != null)
{
device.InputAssembler.SetInputLayout(layout);
device.InputAssembler.SetPrimitiveTopology(
PrimitiveTopology.TriangleList);
device.InputAssembler.SetVertexBuffers(0,
new VertexBufferBinding(vertexBuffer, 3 * sizeof(float), 0));
// States
device.Rasterizer.State = state;
// Render
for (int index = 0; index < technique.PassCount; index++)
{
technique.GetPassByIndex(index).Apply();
device.Draw(3, 0);
}
}
swapChain.Present(0, 0);
}
}
private void cmdCreateGeometry_Click(object sender, EventArgs e)
{
// Vertex Buffer
DataStream data = new DataStream(sizeof(float) * 9, false, true);
data.Write(-1.0f);
data.Write(0.0f);
data.Write(0);
data.Write(0.0f);
data.Write(1.0f);
data.Write(0);
data.Write(1.0f);
data.Write(0.0f);
data.Write(0);
data.Seek(0, System.IO.SeekOrigin.Begin);
vertexBuffer = new SlimDX.Direct3D10.Buffer(device, sizeof(float) * 9
, data, ResourceUsage.Immutable, BindFlags.VertexBuffer,
CpuAccessFlags.None, ResourceOptionFlags.None);
}
private void panel1_Resize(object sender, EventArgs e)
{
CreateSwapChain();
}
}