1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
|
open SlimDX
open SlimDX.D3DCompiler
open SlimDX.Direct3D11
open SlimDX.Windows
open System.Runtime.InteropServices
type TriangleShader(device, elements, size) =
let vertexShader, inputSignature =
let code = @"
struct VShaderOutput {
float4 pos : SV_POSITION;
float4 color : COLOR;
};
VShaderOutput VShader(float2 pos : POSITION, float4 color : COLOR) {
VShaderOutput output;
output.pos = float4(pos, 1, 1);
output.color = color;
return output;
}
"
use bytecode = ShaderBytecode.Compile(code, "VShader", "vs_5_0", ShaderFlags.Debug, EffectFlags.None)
new VertexShader(device, bytecode), ShaderSignature.GetInputSignature(bytecode)
let pixelShader =
let code = @"
float4 PShader(float4 pos : SV_POSITION, float4 color : COLOR) : SV_Target {
return color;
}
"
use bytecode = ShaderBytecode.Compile(code, "PShader", "ps_5_0", ShaderFlags.Debug, EffectFlags.None)
new PixelShader(device, bytecode)
let context = device.ImmediateContext
member this.SetContext(device, vertexBuffer) =
use layout = new InputLayout(device, inputSignature, elements)
context.InputAssembler.InputLayout <- layout
context.InputAssembler.PrimitiveTopology <- PrimitiveTopology.TriangleList
context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, size, 0))
context.VertexShader.Set(vertexShader)
context.PixelShader.Set(pixelShader)
// create random triangle positions and return them in a vertex buffer
let createTriangleVertexBuffer(device, count, size) =
let bufferSizeInBytes = count * size * 3
let stream = new DataStream(int64 bufferSizeInBytes, true, true)
let rnd = System.Random()
for i in 1 .. size * 3 do
stream.Write(float32(rnd.NextDouble()) * 2.0f - 1.0f) // x
stream.Write(float32(rnd.NextDouble()) * 2.0f - 1.0f) // y
stream.Write(rnd.Next()) // color
stream.Position <- 0L
new Buffer(device, stream, bufferSizeInBytes, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0)
open SlimDX.DXGI
[<EntryPoint>]
let main args =
use form = new RenderForm("Test Window")
let width, height = 400, 400
let triangleCount = 20
do form.SetBounds(0, 0, width, height)
let swapChainDescription =
SwapChainDescription(
BufferCount = 1,
Usage = (Usage.RenderTargetOutput),
OutputHandle = form.Handle,
IsWindowed = true,
ModeDescription = ModeDescription(0, 0, Rational(60, 1), Format.R8G8B8A8_UNorm),
SampleDescription = SampleDescription(1, 0))
let result, device, swapChain =
Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.Debug, [|FeatureLevel.Level_11_0|], swapChainDescription)
use renderTarget =
use renderResource = Resource.FromSwapChain<Texture2D>(swapChain, 0)
new RenderTargetView(device, renderResource)
let vertexLayout = [| new InputElement("POSITION", 0, DXGI.Format.R32G32_Float, 0, 0);
new InputElement("COLOR", 0, DXGI.Format.R8G8B8A8_UNorm, 8, 0) |]
let vertexSizeInBytes = 12
let shader = new TriangleShader(device, vertexLayout, vertexSizeInBytes)
let vertexBuffer = createTriangleVertexBuffer(device, triangleCount, vertexSizeInBytes);
let context = device.ImmediateContext
// set viewport
context.Rasterizer.SetViewports(Viewport(0.0f, 0.0f, float32 width, float32 height, 0.0f, 1.0f))
// disable triangle culling and set fill mode to solid
context.Rasterizer.State <- RasterizerState.FromDescription(device, RasterizerStateDescription(CullMode = CullMode.None, FillMode = FillMode.Solid))
// set render target
context.OutputMerger.SetTargets(renderTarget)
// runs per frame
MessagePump.Run(form, MainLoop(fun () ->
// clear render buffer to black
context.ClearRenderTargetView(renderTarget, Color4())
// bind vertex data i.e. where the triangles should be drawn
shader.SetContext(device, vertexBuffer)
// draw triangles
context.Draw(triangleCount, 0)
// copy output buffer to screen
swapChain.Present(0, PresentFlags.None) |> ignore
))
0 // return an integer exit code
|