[PR]
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
プログラミング、3DCGとその他いろいろについて
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
public void CopyResource(Resource source, Resource destination);これは珍しく簡単なメソッドで、解説の必要は無いかもしれません。
OptionFlags = ResourceOptionFlags.StructuredBuffer, StructureByteStride = 配列要素一つのサイズとしてやることでStructuredBufferにすることができます。
ResourceOptionFlagsの値 | 数値 | 説明 |
None | 0 | オプションの指定はなしです。 |
GenerateMipMaps | 1 | 生成するリソースががテクスチャの場合、mipmapの生成を有効にします。これを使う場合、BindFlagsでこのリソースがレンダーターゲットであり、シェーダーリソースであるということを指定しなければいけません。 |
Shared | 2 | 生成するリソースが複数のDirect3Dデバイス間でのデータ共有することを可能にします。ただし2Dのテクスチャでなくてはいけません。 |
TextureCube | 4 | 生成するリソースが6枚のテクスチャから成る、テクスチャキューブになることを可能にします。 |
DrawIndirect | 16 | GPUで生成されたコンテントのインスタンシングを可能にします。たぶんインスタンシングを使って描画するので、直接描画するわけではない、ということなのでしょう。 |
RawBuffer | 32 | 生成するリソースが、ひとかたまりの、バイトアドレスで操作するバッファでになることを可能にします。 |
StructuredBuffer | 64 | 生成するリソースが、Structured Bufferとなることを可能にします。たくさんの構造体が並んだ配列のようなものです。 |
ClampedResource | 128 | DeviceContext.SetMinimumLod()メソッドを使ったときに、mipmapのclampを有効にします。 |
KeyedMutex | 256 | SlimDX.DXGI.KeyedMutexクラスの、KeyedMutex.Acquire()メソッドとKeydMutex.Release()メソッドを使ったときに、シンクロするようになります。 |
GdiCompatible | 512 | リソースがGDIと互換性を持てます。これを指定するとSlimDX.Direct2D.GdiInteropRenderTargetクラスのGetDC()メソッドを使ってGDIで描画できます。 |
using System.Collections.Generic; using System.Linq; using SlimDX; using SlimDX.Direct3D11; class Program { static void Main(string[] args) { Device device = new Device(DriverType.Hardware); Buffer onlyGpuBuffer = createStructuredBuffer(device, Enumerable.Range(10, 10).ToArray()); writeBuffer(device, onlyGpuBuffer); } static void writeBuffer(Device device, Buffer buffer) { Buffer cpuAccessibleBuffer = createCpuAccessibleBuffer(device, Enumerable.Range(0, 10).ToArray()); device.ImmediateContext.CopyResource(buffer, cpuAccessibleBuffer); int[] readBack = readBackFromGpu(cpuAccessibleBuffer); foreach (var number in readBack) { System.Console.WriteLine(number); } } static Buffer createStructuredBuffer(Device device, int[] initialData) { DataStream initialDataStream = new DataStream(initialData, true, true); return new Buffer( device, initialDataStream, new BufferDescription { SizeInBytes = (int)initialDataStream.Length, OptionFlags = ResourceOptionFlags.StructuredBuffer, StructureByteStride = sizeof(int) } ); } static Buffer createCpuAccessibleBuffer(Device device, int[] initialData) { DataStream initialDataStream = new DataStream(initialData, true, true); return new Buffer( device, initialDataStream, new BufferDescription { SizeInBytes = (int)initialDataStream.Length, CpuAccessFlags = CpuAccessFlags.Read, Usage = ResourceUsage.Staging } ); } static int[] readBackFromGpu(Buffer from) { DataBox data = from.Device.ImmediateContext.MapSubresource( from, MapMode.Read, MapFlags.None ); return getArrayInt32(data.Data); } static int[] getArrayInt32(DataStream stream) { int[] buffer = new int[stream.Length / sizeof(int)]; stream.ReadRange(buffer, 0, buffer.Length); return buffer; } }このプログラムはまず、
10 11 12 13 14 15 16 17 18 19ここで表示されているのは
using System.Collections.Generic; using System.Linq; using SlimDX; using SlimDX.Direct3D11; class Program { static void Main(string[] args) { Device device = new Device(DriverType.Hardware); Buffer buffer = createCpuAccessibleBuffer(device, Enumerable.Range(0, 10).ToArray()); int[] readBack = readBackFromGpu(buffer); foreach (var number in readBack) { System.Console.WriteLine(number); } } private static Buffer createCpuAccessibleBuffer(Device device, int[] initialData) { DataStream initialDataStream = new DataStream(initialData, true, true); return new Buffer( device, initialDataStream, new BufferDescription { SizeInBytes = (int)initialDataStream.Length, CpuAccessFlags = CpuAccessFlags.Read, Usage = ResourceUsage.Staging } ); } static int[] readBackFromGpu(Buffer from) { DataBox data = from.Device.ImmediateContext.MapSubresource( from, MapMode.Read, MapFlags.None ); return getArrayInt32(data.Data); } static int[] getArrayInt32(DataStream stream) { int[] buffer = new int[stream.Length / sizeof(int)]; stream.ReadRange(buffer, 0, buffer.Length); return buffer; } }コードはこれだけです。
0 1 2 3 4 5 6 7 8 9ここで表示しているのはGPUにあるバッファの内容をCPU側に写しとった配列です。
public class Device : ComObjectコンストラクタは8個用意されていますが、今回必要なのは
public Device(DriverType driverType);deviceTypeはデバイスの種類で、つぎの6つの中から選びます。
DeviceTypeの値 | 説明 |
Unknown | タイプが不明 |
Hardware | Direct3Dの機能を持つハードウェアです。まずほとんどのばあいこれを使ってDeviceクラスを初期化することになります。ハードウェアを使うためかなり速いです。というかこれ以外では遅すぎてまず通常目的では使えません。これを使いましょう。 |
Reference | リファレンスドライバです。リファレンスドライバはソフトウェアで動いているため遅いです。遅いです―が正確で、デバッグ時やDirectXの機能をテストするというようなときには悪くはないのかもしれません。ただ、実際のアプリケーションで使う為のものではありません。 |
Null | Nullドライバです。これはリファレンスドライバから描画機能がなくなったようなものです。これもデバッグ用で、まず普通のアプリケーションで使うためのものではありません。 |
Software | Softwareドライバです。これは完全にソフトウェアで実装されています。やはり遅いため普通のアプリケーションで使うためのものではありません。 |
Warp | WARPドライバです。これもソフトウェアで動きますが、パフォーマンスは高いです。 |
public DeviceContext ImmediateContext { get; }と、いうよりDeviceクラスはほとんど抜け殻のようなもので、
public class Buffer : ResourceこのバッファというものはGPUに存在するデータの塊のようなもので、
public Buffer(Device device, DataStream data, BufferDescription description);deviceはこのバッファを作るデバイスです。
public class DataStream : Stream, IDisposableコンストラクタは3種類用意されていますが、
public DataStream(Array userBuffer, bool canRead, bool canWrite);
public T[] ReadRange(int count) where T : struct; public int ReadRange (T[] buffer, int offset, int count) where T : struct;
プロパティ名 | 型 | 説明 |
BindFlags | BindFlags | パイプライン中でどのように使われるか、を表します。 たとえば頂点バッファとして使われるか?インデックスバッファとして使われるか?定数バッファとして使われるのか?シェーダーのリソースとして使われるのか?ストリームの出力として使われるのか?レンダーターゲットとして使われるのか?デプスステンシルバッファとして使われるのか?アンオーダードアクセス(複数のスレッドから同時に読み書き可能な)リソースとして使われるのか? ・・・・・・などです |
CpuAccessFlags | CpuAccessFlags | このバッファにCPUがいかほどのアクセス権限を持っているかを表します。None, Write, Readの3種類があります。 |
OptionFlags | ResourceOptionFlags | その他のオプションです。 たとえば、MipMapを生成するか?複数のデバイス間で共有されるか?TextureCubeか?インスタンシングを有効にするか?RawBufferか?StructuredBufferか?深度バイアスはどうするか?KeyedMutexか?GDIと互換性があるか? ・・・・・・などです。 |
SizeInBytes | int | バッファが何バイトか、を表します。 |
StructureByteStride | int | StructuredBufferとして使用する場合(OptionFlagsでそのように指定するのですが)に使います。ひとつの構造体のサイズが何バイトかを表します。 |
Usage | ResourceUsage | バッファの使われ方を表します。GPUが読み書きのできるDefault、GPUで読み取りのみ可能なImmutable、GPUからは読み取りのみCPUからは書き込みのみのDynamic、GPUからCPUへデータを転送できるStagingの4つです。 |
public DataBox MapSubresource( Resource resource, MapMode mode, MapFlags flags);resourceはメモリに展開するリソース、今回の場合はバッファです。
MapModeの名前 | 説明 |
Read | リソースは読み取り用にマップされます。ただしリソースが読み取りアクセス可能なように生成されていなければいけません。 |
Write | リソースは書き込み用にマップされます。ただしリソースが書き込みアクセス可能なように生成されていなければいけません。 |
ReadWrite | リソースは読み書き用にマップされます。ただしリソースが読み書きアクセス可能なように生成されていなければいけません。 |
WriteDiscard | リソースは書き込み用にマップされますが、以前の情報は未定義になります。ただしリソースが書き込みアクセス可能なように生成されていなければいけません。 |
WriteNoOverwrite | リソースは書き込み用にマップされますが、リソースのすでに存在しているコンテンツは上書きできません。このフラグは頂点バッファとインデックスバッファでのみ有効です。リソースは書き込みアクセス可能なように生成されていなければいけません。 |
MapFlagsの名前 | 説明 |
None | リソースが使えるようになるまで待ちます。 |
DoNotWait | リソースが使えるようになるまで待ちません。GPUがCPUからのアクセスをブロックするようであればWasStillRenderingを返します。 |
public DataStream Data { get; }DataはSystem.IO.Streamを継承したSlimDX.DataStreamクラスです。
using Microsoft.WindowsAPICodePack.DirectX.Direct3D;using Microsoft.WindowsAPICodePack.DirectX.Direct3D11;using Microsoft.WindowsAPICodePack.DirectX.Graphics;using System.IO;using System.Runtime.InteropServices;class Program{static void Main(){using (Game game = new MyGame()){game.Run();}}}class Game : System.Windows.Forms.Form{protected DeviceContext DeviceContext;protected SwapChain SwapChain;protected RenderTargetView RenderTargetView;public void Run(){D3DDevice device = initDevice();LoadGraphicsContent(device);Show();while (Created){Draw();System.Windows.Forms.Application.DoEvents();}}private D3DDevice initDevice(){D3DDevice device = D3DDevice.CreateDeviceAndSwapChain(this.Handle);this.SwapChain = device.SwapChain;this.DeviceContext = device.ImmediateContext;using (Texture2D texture2D = SwapChain.GetBuffer<Texture2D>(0)){this.RenderTargetView = device.CreateRenderTargetView(texture2D);DeviceContext.OM.RenderTargets = new OutputMergerRenderTargets(new[] { RenderTargetView });}DeviceContext.RS.Viewports = new[]{new Viewport{Width = ClientSize.Width,Height = ClientSize.Height,MaxDepth = 1}};return device;}protected virtual void LoadGraphicsContent(D3DDevice device) { }protected virtual void Draw() { }protected D3DBuffer CreateVertexBuffer<T>(D3DDevice device, T[] vertices) where T : struct{int vertexSize = Marshal.SizeOf(typeof(T));System.IntPtr verticesPointer = Marshal.AllocCoTaskMem(vertices.Length * vertexSize);for (int i = 0; i < vertices.Length; i++){Marshal.StructureToPtr(vertices[i], verticesPointer + vertexSize * i, false);}D3DBuffer result = device.CreateBuffer(new BufferDescription{ByteWidth = (uint)(vertexSize * vertices.Length),BindingOptions = BindingOptions.VertexBuffer,},new SubresourceData{SystemMemory = verticesPointer});Marshal.FreeCoTaskMem(verticesPointer);return result;}protected void ToNative(object structure, System.Action<System.IntPtr> nativeAction){System.IntPtr nativeConstantBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyCamera)));Marshal.StructureToPtr(structure, nativeConstantBuffer, false);nativeAction(nativeConstantBuffer);Marshal.FreeHGlobal(nativeConstantBuffer);}}struct VertexPositionColor{public Vector3F Position;public Vector3F Color;public static readonly InputElementDescription[] VertexElements = new[]{new InputElementDescription{SemanticName = "SV_Position",Format = Format.R32G32B32Float,},new InputElementDescription{SemanticName = "COLOR",Format = Format.R32G32B32Float,AlignedByteOffset = uint.MaxValue //MaxValueにするとオフセットを自動的に決定}};}struct MyCamera{public Matrix4x4F View;public Matrix4x4F Projection;public static int SizeInBytes{get{return Marshal.SizeOf(typeof(MyCamera));}}}class MyGame : Game{D3DBuffer cameraConstantBuffer;protected override void Draw(){this.DeviceContext.ClearRenderTargetView(RenderTargetView, new ColorRgba(0.39f, 0.58f, 0.93f, 1));updateCamera();this.DeviceContext.Draw(3, 0);this.SwapChain.Present(0, PresentOptions.None);}private void updateCamera(){double time = System.Environment.TickCount / 100d;Matrix4x4F view = MatrixHelper.CreateLookAt(new Vector3F((float)System.Math.Cos(time), 0, (float)System.Math.Sin(time)),new Vector3F(0, 0, 0),new Vector3F(0, 1, 0));Matrix4x4F projection = MatrixHelper.CreatePerspectiveFieldOfView((float)System.Math.PI / 2,(float)ClientSize.Width / ClientSize.Height,0.1f, 1000);ToNative(new MyCamera{View = MatrixHelper.Transpose(view),Projection = MatrixHelper.Transpose(projection)},nativeCamera =>{DeviceContext.UpdateSubresource(cameraConstantBuffer,0,nativeCamera,0,0);});DeviceContext.VS.SetConstantBuffers(0, new[] { cameraConstantBuffer });}protected override void LoadGraphicsContent(D3DDevice device){initShadersAndInputLayout(device);initTriangleToDraw(device);initCamera(device);}private void initShadersAndInputLayout(D3DDevice device){using (Stream vertexShaderBinary = File.Open("MyShader.vs", FileMode.Open)){this.DeviceContext.VS.Shader = device.CreateVertexShader(vertexShaderBinary);vertexShaderBinary.Position = 0;this.DeviceContext.IA.InputLayout = createInputLayout(device, vertexShaderBinary);}using (Stream pixelShaderBinary = System.IO.File.Open("MyShader.ps", FileMode.Open)){this.DeviceContext.PS.Shader = device.CreatePixelShader(pixelShaderBinary);}}private InputLayout createInputLayout(D3DDevice device, Stream vertexShaderBinary){return device.CreateInputLayout(VertexPositionColor.VertexElements,vertexShaderBinary);}private void initTriangleToDraw(D3DDevice device){VertexPositionColor[] vertices = new []{new VertexPositionColor{ Position = new Vector3F(0, 0.5f, 0), Color = new Vector3F(1, 1, 1) },new VertexPositionColor{ Position = new Vector3F(0.5f, 0, 0), Color = new Vector3F(0, 0, 1) },new VertexPositionColor{ Position = new Vector3F(-0.5f, 0, 0), Color = new Vector3F(1, 0, 0) },};D3DBuffer vertexBuffer = CreateVertexBuffer(device, vertices);this.DeviceContext.IA.SetVertexBuffers(0,new D3DBuffer[] { vertexBuffer },new uint[] { (uint)Marshal.SizeOf(typeof(VertexPositionColor)) },new uint[] { 0 });this.DeviceContext.IA.PrimitiveTopology = PrimitiveTopology.TriangleList;}private void initCamera(D3DDevice device){ToNative(new MyCamera {},nativeCamera =>{this.cameraConstantBuffer = device.CreateBuffer(new BufferDescription{ByteWidth = (uint)MyCamera.SizeInBytes,BindingOptions = BindingOptions.ConstantBuffer},//nativeCameraの中身はカラなので//これはいらないように一見見えますが、//これがないと何故か例外をスローします。//今後改善なりなんなりがあるのでしょうか?new SubresourceData{SystemMemory = nativeCamera});});}}
using Microsoft.WindowsAPICodePack.DirectX.Direct3D;class MatrixHelper{public static Matrix4x4F CreateLookAt(Vector3F cameraPosition, Vector3F cameraTarget, Vector3F cameraUpVector){Vector3F newZ = (cameraPosition - cameraTarget).Normalize();Vector3F newX = Vector3F.Cross(cameraUpVector, newZ).Normalize();Vector3F newY = Vector3F.Cross(newZ, newX);return new Matrix4x4F(newX.X,newY.X,newZ.X,0,newX.Y,newY.Y,newZ.Y,0,newX.Z,newY.Z,newZ.Z,0,-Vector3F.Dot(newX, cameraPosition),-Vector3F.Dot(newY, cameraPosition),-Vector3F.Dot(newZ, cameraPosition),1f);}public static Matrix4x4F CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio,float nearPlaneDistance, float farPlaneDistance){return new Matrix4x4F{M11 = (float)(1 / (aspectRatio * System.Math.Tan(fieldOfView / 2))),M22 = (float)(1 / System.Math.Tan(fieldOfView / 2)),M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance),M34 = -1,M43 = (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance),};}public static Matrix4x4F Transpose(Matrix4x4F matrix){return new Matrix4x4F(matrix.M11, matrix.M21, matrix.M31, matrix.M41,matrix.M12, matrix.M22, matrix.M32, matrix.M42,matrix.M13, matrix.M23, matrix.M33, matrix.M43,matrix.M14, matrix.M24, matrix.M34, matrix.M44);}}
cbuffer MyCamera{matrix View;matrix Projection;}struct VertexPositionColor{float4 Position : SV_Position;float4 Color : COLOR;};VertexPositionColor MyVertexShader(VertexPositionColor input){VertexPositionColor output = input;output.Position = mul(output.Position, View);output.Position = mul(output.Position, Projection);return output;}float4 MyPixelShader(VertexPositionColor input) : SV_Target{return input.Color;}
前回からの変更点はusing Microsoft.WindowsAPICodePack.DirectX.Direct3D;using Microsoft.WindowsAPICodePack.DirectX.Direct3D11;using Microsoft.WindowsAPICodePack.DirectX.Graphics;using System.IO;using System.Runtime.InteropServices;class Program{static void Main(){using (Game game = new MyGame()){game.Run();}}}class Game : System.Windows.Forms.Form{protected DeviceContext DeviceContext;protected SwapChain SwapChain;protected RenderTargetView RenderTargetView;public void Run(){D3DDevice device = initDevice();LoadGraphicsContent(device);Show();while (Created){Draw();System.Windows.Forms.Application.DoEvents();}}private D3DDevice initDevice(){D3DDevice device = D3DDevice.CreateDeviceAndSwapChain(this.Handle);this.SwapChain = device.SwapChain;this.DeviceContext = device.ImmediateContext;using (Texture2D texture2D = SwapChain.GetBuffer<Texture2D>(0)){this.RenderTargetView = device.CreateRenderTargetView(texture2D);DeviceContext.OM.RenderTargets = new OutputMergerRenderTargets(new[] { RenderTargetView });}DeviceContext.RS.Viewports = new[]{new Viewport{Width = ClientSize.Width,Height = ClientSize.Height,MaxDepth = 1}};return device;}protected virtual void LoadGraphicsContent(D3DDevice device) { }protected virtual void Draw() { }//ジェネリクスな型Tをネイティブに変換するのは骨が折れます。//XNAでは別の方法を使っているようですが…protected D3DBuffer CreateVertexBuffer<T>(D3DDevice device, T[] vertices) where T : struct{int vertexSize = Marshal.SizeOf(typeof(T));System.IntPtr verticesPointer = Marshal.AllocCoTaskMem(vertices.Length * vertexSize);for (int i = 0; i < vertices.Length; i++){Marshal.StructureToPtr(vertices[i], verticesPointer + vertexSize * i, false);}D3DBuffer result = device.CreateBuffer(new BufferDescription{ByteWidth = (uint)(vertexSize * vertices.Length),BindingOptions = BindingOptions.VertexBuffer,},new SubresourceData{SystemMemory = verticesPointer});Marshal.FreeCoTaskMem(verticesPointer);return result;}}struct VertexPositionColor{public Vector3F Position;public Vector3F Color;public static readonly InputElementDescription[] VertexElements = new[]{new InputElementDescription{SemanticName = "SV_Position",Format = Format.R32G32B32Float,},new InputElementDescription{SemanticName = "COLOR",Format = Format.R32G32B32Float,AlignedByteOffset = uint.MaxValue //MaxValueにするとオフセットを自動的に決定}};}class MyGame : Game{protected override void Draw(){this.DeviceContext.ClearRenderTargetView(RenderTargetView, new ColorRgba(0.39f, 0.58f, 0.93f, 1));this.DeviceContext.Draw(3, 0);this.SwapChain.Present(0, PresentOptions.None);}protected override void LoadGraphicsContent(D3DDevice device){initShadersAndInputLayout(device);initTriangleToDraw(device);}private void initShadersAndInputLayout(D3DDevice device){using (Stream vertexShaderBinary = File.Open("MyShader.vs", FileMode.Open)){this.DeviceContext.VS.Shader = device.CreateVertexShader(vertexShaderBinary);vertexShaderBinary.Position = 0;this.DeviceContext.IA.InputLayout = createInputLayout(device, vertexShaderBinary);}using (Stream pixelShaderBinary = System.IO.File.Open("MyShader.ps", FileMode.Open)){this.DeviceContext.PS.Shader = device.CreatePixelShader(pixelShaderBinary);}}private InputLayout createInputLayout(D3DDevice device, Stream vertexShaderBinary){return device.CreateInputLayout(VertexPositionColor.VertexElements,vertexShaderBinary);}private void initTriangleToDraw(D3DDevice device){VertexPositionColor[] vertices = new []{new VertexPositionColor{ Position = new Vector3F(0, 0.5f, 0), Color = new Vector3F(1, 1, 1) },new VertexPositionColor{ Position = new Vector3F(0.5f, 0, 0), Color = new Vector3F(0, 0, 1) },new VertexPositionColor{ Position = new Vector3F(-0.5f, 0, 0), Color = new Vector3F(1, 0, 0) },};D3DBuffer vertexBuffer = CreateVertexBuffer(device, vertices);this.DeviceContext.IA.SetVertexBuffers(0,new D3DBuffer[] { vertexBuffer },new uint[] { (uint)Marshal.SizeOf(typeof(VertexPositionColor)) },new uint[] { 0 });this.DeviceContext.IA.PrimitiveTopology = PrimitiveTopology.TriangleList;}}
例によってこのファイルはfxc.exeを使ってコンパイルしてください。struct VertexPositionColor{float4 Position : SV_Position;float4 Color : COLOR;};VertexPositionColor MyVertexShader(VertexPositionColor input){return input;}float4 MyPixelShader(VertexPositionColor input) : SV_Target{return input.Color;}
あまりにも長いのでクラスを2分割しました。using Microsoft.WindowsAPICodePack.DirectX.Direct3D;using Microsoft.WindowsAPICodePack.DirectX.Direct3D11;using Microsoft.WindowsAPICodePack.DirectX.Graphics;using System.IO;using System.Runtime.InteropServices;class Program{static void Main(){using (Game game = new MyGame()){game.Run();}}}class Game : System.Windows.Forms.Form{protected DeviceContext DeviceContext;protected SwapChain SwapChain;protected RenderTargetView RenderTargetView;public void Run(){D3DDevice device = initDevice();LoadGraphicsContent(device);Show();while (Created){Draw();System.Windows.Forms.Application.DoEvents();}}private D3DDevice initDevice(){D3DDevice device = D3DDevice.CreateDeviceAndSwapChain(this.Handle);this.SwapChain = device.SwapChain;this.DeviceContext = device.ImmediateContext;using (Texture2D texture2D = SwapChain.GetBuffer<Texture2D>(0)){this.RenderTargetView = device.CreateRenderTargetView(texture2D);DeviceContext.OM.RenderTargets = new OutputMergerRenderTargets(new[] { RenderTargetView });}DeviceContext.RS.Viewports = new[]{new Viewport{Width = ClientSize.Width,Height = ClientSize.Height,MaxDepth = 1}};return device;}protected virtual void LoadGraphicsContent(D3DDevice device) { }protected virtual void Draw() { }protected unsafe D3DBuffer CreateVertexBuffer(D3DDevice device, Vector3F[] vertices){fixed (Vector3F* fixedVertices = vertices){return device.CreateBuffer(new BufferDescription{ByteWidth = (uint)(Marshal.SizeOf(typeof(Vector3F)) * vertices.Length),BindingOptions = BindingOptions.VertexBuffer,},new SubresourceData{SystemMemory = new System.IntPtr(fixedVertices)});}}}class MyGame : Game{protected override void Draw(){this.DeviceContext.ClearRenderTargetView(RenderTargetView, new ColorRgba(0, 0, 1, 1));this.DeviceContext.Draw(3, 0);this.SwapChain.Present(0, PresentOptions.None);}protected override void LoadGraphicsContent(D3DDevice device){initShadersAndInputLayout(device);initTriangleToDraw(device);}private void initShadersAndInputLayout(D3DDevice device){using (Stream vertexShaderBinary = File.Open("MyShader.vs", FileMode.Open)){this.DeviceContext.VS.Shader = device.CreateVertexShader(vertexShaderBinary);vertexShaderBinary.Position = 0;this.DeviceContext.IA.InputLayout = createInputLayout(device, vertexShaderBinary);}using (Stream pixelShaderBinary = System.IO.File.Open("MyShader.ps", FileMode.Open)){this.DeviceContext.PS.Shader = device.CreatePixelShader(pixelShaderBinary);}}private InputLayout createInputLayout(D3DDevice device, Stream vertexShaderBinary){return device.CreateInputLayout(new[] {new InputElementDescription{SemanticName = "SV_Position",Format = Format.R32G32B32Float,}},vertexShaderBinary);}private void initTriangleToDraw(D3DDevice device){Vector3F[] vertices = new Vector3F[]{new Vector3F(0, 0.5f, 0),new Vector3F(0.5f, 0, 0),new Vector3F(-0.5f, 0, 0)};D3DBuffer vertexBuffer = CreateVertexBuffer(device, vertices);this.DeviceContext.IA.SetVertexBuffers(0,new D3DBuffer[] { vertexBuffer },new uint[] { (uint)Marshal.SizeOf(typeof(Vector3F)) },new uint[] { 0 });this.DeviceContext.IA.PrimitiveTopology = PrimitiveTopology.TriangleList;}}
説明 | XNAで言うと | |
シェーダー(頂点シェーダとピクセルシェーダ) | 頂点データがどのような処理をされて描画されるかを制御します。このコードではMyShader.vsとMyShader.psというファイルから読み込んでいます。 | Effect |
インプットレイアウト | 頂点データの意味を表します。(何バイト目が色のデータだ、など) | VertexDeclaration |
頂点バッファ | 描画する図形の頂点データを保持します。 | VertexBuffer |
ビューポート | 描画先の領域です。 | Viewport |
この意味は、ポリゴンの「頂点はそのままなにも動かさず、色は白にせよ」float4 MyVertexShader(float4 position : SV_Position) : SV_Position{return position;}float4 MyPixelShader() : SV_Target{return float4(1, 1, 1, 1);}
意味は"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86\fxc.exe" /T vs_4_0 /E MyVertexShader /Fo MyShader.vs MyShader.fx@pause"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86\fxc.exe" /T ps_4_0 /E MyPixelShader /Fo MyShader.ps MyShader.fx@pause
/T | 対象とするプロファイル。例えばvs_4_0やps_4_0です。これを入れ違えたり間違ってもfx_4_0などにしないでください。C#側からArgumentExceptionがスローされます。 |
/E | エントリーポイント。頂点シェーダなら頂点シェーダのメソッド名、ピクセルシェーダならピクセルシェーダのメソッド名です。 |
/Fo | 出力ファイル名 |