OSDN Git Service

テクスチャ クラスの Dispose 漏れを修正。
[strokestylet/CsWin10Desktop3.git] / FDK24 / メディア / テクスチャ.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Linq;
5
6 namespace FDK.メディア
7 {
8         public class テクスチャ : FDK.Activity
9         {
10                 // (1) 個別項目
11
12                 /// <summary>
13                 /// 0:透明~1:不透明
14                 /// </summary>
15                 public float 不透明度 { get; set; } = 1f;
16                 public bool 加算合成する { get; set; } = false;
17                 public SharpDX.Size2F サイズdpx => this.ShaderResourceViewSize;
18                 public SharpDX.Matrix 等倍スケーリング行列 => SharpDX.Matrix.Scaling( this.サイズdpx.Width, this.サイズdpx.Height, 1f );
19
20                 public テクスチャ( string 画像ファイルパス )
21                 {
22                         this.画像ファイルパス = 画像ファイルパス;
23                 }
24                 protected override void Onデバイス依存リソースの作成( デバイスリソース dr )
25                 {
26                         var d3dDevice = (SharpDX.Direct3D11.Device) null;
27
28                         using( var d3dLock = new FDK.同期.AutoD3DDeviceLock( dr.DXGIDeviceManager, out d3dDevice ) )
29                         using( d3dDevice )
30                         {
31                                 #region " 定数バッファ "
32                                 //----------------
33                                 var cBufferDesc = new SharpDX.Direct3D11.BufferDescription() {
34                                         Usage = SharpDX.Direct3D11.ResourceUsage.Dynamic,   // 動的使用法
35                                         BindFlags = SharpDX.Direct3D11.BindFlags.ConstantBuffer,    // 定数バッファ
36                                         CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Write,   // CPUから書き込む
37                                         OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None,
38                                         SizeInBytes = SharpDX.Utilities.SizeOf<ST定数バッファの転送元データ>(),   // バッファサイズ
39                                         StructureByteStride = 0,
40                                 };
41                                 this.ConstantBuffer = new SharpDX.Direct3D11.Buffer( d3dDevice, cBufferDesc );
42                                 //----------------
43                                 #endregion
44                                 #region " シェーダーリソースビュー "
45                                 //----------------
46                                 this.ShaderResourceView = FDK.Utilities.CreateShaderResourceViewFromFile(
47                                         d3dDevice, FDK.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( this.画像ファイルパス ), out this.ShaderResourceViewSize );
48                                 //----------------
49                                 #endregion
50                         }
51                 }
52                 protected override void Onデバイス依存リソースの解放( デバイスリソース dr )
53                 {
54                         FDK.Utilities.解放する( ref this.ShaderResourceView );
55                         FDK.Utilities.解放する( ref this.ConstantBuffer );
56                 }
57
58                 /// <param name="転送元矩形">テクスチャ座標(値域0~1)で指定する。</param>
59                 public void 進行描画する( デバイスリソース dr, SharpDX.Matrix ワールド行列変換, SharpDX.RectangleF? 転送元矩形 = null )
60                 {
61                         var d3dDevice = (SharpDX.Direct3D11.Device) null;
62                         using( var d3dLock = new FDK.同期.AutoD3DDeviceLock( dr.DXGIDeviceManager, out d3dDevice ) )
63                         using( d3dDevice )
64                         using( var d3dContext = d3dDevice.ImmediateContext )
65                         {
66                                 #region " 定数バッファを更新する。"
67                                 //----------------
68                                 {
69                                         // ワールド変換行列
70                                         ワールド行列変換.Transpose();    // 転置
71                                         this.定数バッファの転送元データ.World = ワールド行列変換;
72
73                                         // ビュー変換行列
74                                         this.定数バッファの転送元データ.View = dr.ビュー変換行列;
75
76                                         // 射影変換行列
77                                         this.定数バッファの転送元データ.Projection = dr.射影変換行列;
78
79                                         // 描画元矩形
80                                         if( null == 転送元矩形 )
81                                                 転送元矩形 = new SharpDX.RectangleF( 0f, 0f, 1f, 1f );
82                                         this.定数バッファの転送元データ.TexLeft = 転送元矩形.Value.Left;
83                                         this.定数バッファの転送元データ.TexTop = 転送元矩形.Value.Top;
84                                         this.定数バッファの転送元データ.TexRight = 転送元矩形.Value.Right;
85                                         this.定数バッファの転送元データ.TexBottom = 転送元矩形.Value.Bottom;
86
87                                         // アルファ
88                                         this.定数バッファの転送元データ.TexAlpha = this.不透明度;
89                                         this.定数バッファの転送元データ.dummy1 = 0f;
90                                         this.定数バッファの転送元データ.dummy2 = 0f;
91                                         this.定数バッファの転送元データ.dummy3 = 0f;
92
93                                         // 定数バッファへ書き込む。
94                                         var dataBox = d3dContext.MapSubresource(
95                                                 resourceRef: this.ConstantBuffer,
96                                                 subresource: 0,
97                                                 mapType: SharpDX.Direct3D11.MapMode.WriteDiscard,
98                                                 mapFlags: SharpDX.Direct3D11.MapFlags.None );
99                                         SharpDX.Utilities.Write( dataBox.DataPointer, ref this.定数バッファの転送元データ );
100                                         d3dContext.UnmapSubresource( this.ConstantBuffer, 0 );
101                                 }
102                                 //----------------
103                                 #endregion
104                                 #region " 3Dパイプラインを設定する。"
105                                 //----------------
106                                 // 入力アセンブラ
107                                 d3dContext.InputAssembler.InputLayout = null;
108                                 d3dContext.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleStrip;
109
110                                 // 頂点シェーダ
111                                 d3dContext.VertexShader.Set( テクスチャ.VertexShader );
112                                 d3dContext.VertexShader.SetConstantBuffers( 0, this.ConstantBuffer );
113
114                                 // ジオメトリシェーダ
115                                 d3dContext.GeometryShader.Set( null );
116
117                                 // ラスタライザ
118                                 d3dContext.Rasterizer.SetViewports( dr.D3DViewPort );
119                                 d3dContext.Rasterizer.State = テクスチャ.RasterizerState;
120
121                                 // ピクセルシェーダ
122                                 d3dContext.PixelShader.Set( テクスチャ.PixelShader );
123                                 d3dContext.PixelShader.SetConstantBuffers( 0, this.ConstantBuffer );
124                                 d3dContext.PixelShader.SetShaderResources( 0, 1, this.ShaderResourceView );
125                                 d3dContext.PixelShader.SetSamplers( 0, 1, テクスチャ.SamplerState );
126
127                                 // 出力マージャ
128                                 d3dContext.OutputMerger.SetTargets( dr.D3DDepthStencilView, dr.D3DRenderTargetView );
129                                 d3dContext.OutputMerger.SetBlendState(
130                                         ( this.加算合成する ) ? テクスチャ.BlendStateAdd : テクスチャ.BlendStateNormal,
131                                         new SharpDX.Mathematics.Interop.RawColor4( 0f, 0f, 0f, 0f ),
132                                         -1 );
133                                 d3dContext.OutputMerger.SetDepthStencilState( dr.D3DDepthStencilState, 0 );
134                                 //----------------
135                                 #endregion
136
137                                 // 頂点バッファとインデックスバッファを使わずに 4 つの頂点を描画する。
138                                 d3dContext.Draw( vertexCount: 4, startVertexLocation: 0 );
139                         }
140                 }
141
142                 protected string 画像ファイルパス = null;
143                 protected struct ST定数バッファの転送元データ
144                 {
145                         public SharpDX.Matrix World;      // ワールド変換行列
146                         public SharpDX.Matrix View;       // ビュー変換行列
147                         public SharpDX.Matrix Projection; // 透視変換行列
148
149                         public float TexLeft;   // 描画元矩形の左u座標(0~1)
150                         public float TexTop;    // 描画元矩形の上v座標(0~1)
151                         public float TexRight;  // 描画元矩形の右u座標(0~1)
152                         public float TexBottom; // 描画元矩形の下v座標(0~1)
153
154                         public float TexAlpha;  // テクスチャに乗じるアルファ値(0~1)
155                         public float dummy1;    // float4境界に合わせるためのダミー
156                         public float dummy2;    // float4境界に合わせるためのダミー
157                         public float dummy3;    // float4境界に合わせるためのダミー
158                 };
159                 protected ST定数バッファの転送元データ 定数バッファの転送元データ;
160                 protected SharpDX.Direct3D11.Buffer ConstantBuffer = null;
161                 protected SharpDX.Direct3D11.ShaderResourceView ShaderResourceView = null;
162                 protected SharpDX.Size2F ShaderResourceViewSize;
163
164                 // (2) 全インスタンス共通項目(static)
165
166                 public static void 共有リソースを作成する( FDK.メディア.デバイスリソース dr )
167                 {
168                         var d3dDevice = (SharpDX.Direct3D11.Device) null;
169                         using( var d3dLock = new FDK.同期.AutoD3DDeviceLock( dr.DXGIDeviceManager, out d3dDevice ) )
170                         using( d3dDevice )
171                         {
172                                 #region " 頂点シェーダ "
173                                 //----------------
174                                 var シェーダコンパイルのオプション =
175                                         SharpDX.D3DCompiler.ShaderFlags.Debug |
176                                         SharpDX.D3DCompiler.ShaderFlags.SkipOptimization |
177                                         SharpDX.D3DCompiler.ShaderFlags.EnableStrictness |
178                                         SharpDX.D3DCompiler.ShaderFlags.PackMatrixColumnMajor;
179
180                                 // シェーダコードをコンパイルする。
181                                 using( var code = SharpDX.D3DCompiler.ShaderBytecode.Compile(
182                                         FDK.Properties.Resources.テクスチャ用シェーダコード,
183                                         "VS", "vs_4_0", シェーダコンパイルのオプション ) )
184                                 {
185                                         // 頂点シェーダを生成する。
186                                         テクスチャ.VertexShader = new SharpDX.Direct3D11.VertexShader( d3dDevice, code );
187                                 }
188                                 //----------------
189                                 #endregion
190                                 #region " ピクセルシェーダ "
191                                 //----------------
192                                 // シェーダコードをコンパイルする。
193                                 using( var code = SharpDX.D3DCompiler.ShaderBytecode.Compile(
194                                         FDK.Properties.Resources.テクスチャ用シェーダコード,
195                                         "PS", "ps_4_0", シェーダコンパイルのオプション ) )
196                                 {
197                                         // ピクセルシェーダを作成する。
198                                         テクスチャ.PixelShader = new SharpDX.Direct3D11.PixelShader( d3dDevice, code );
199                                 }
200                                 //----------------
201                                 #endregion
202                                 #region " ブレンドステート(通常)"
203                                 //----------------
204                                 var BlendStateNorm = new SharpDX.Direct3D11.BlendStateDescription() {
205                                         AlphaToCoverageEnable = false,  // アルファマスクで透過する(するならZバッファ必須)
206                                         IndependentBlendEnable = false, // 個別設定。false なら BendStateDescription.RenderTarget[0] だけが有効で、[1~7] は無視される。
207                                 };
208                                 BlendStateNorm.RenderTarget[ 0 ].IsBlendEnabled = true; // true ならブレンディングが有効。
209                                 BlendStateNorm.RenderTarget[ 0 ].RenderTargetWriteMask = SharpDX.Direct3D11.ColorWriteMaskFlags.All;        // RGBA の書き込みマスク。
210
211                                 // アルファ値のブレンディング設定 ... 特になし
212                                 BlendStateNorm.RenderTarget[ 0 ].SourceAlphaBlend = SharpDX.Direct3D11.BlendOption.One;
213                                 BlendStateNorm.RenderTarget[ 0 ].DestinationAlphaBlend = SharpDX.Direct3D11.BlendOption.Zero;
214                                 BlendStateNorm.RenderTarget[ 0 ].AlphaBlendOperation = SharpDX.Direct3D11.BlendOperation.Add;
215
216                                 // 色値のブレンディング設定 ... アルファ強度に応じた透明合成(テクスチャのアルファ値は、テクスチャのアルファ×ピクセルシェーダでの全体アルファとする(HLSL参照))
217                                 BlendStateNorm.RenderTarget[ 0 ].SourceBlend = SharpDX.Direct3D11.BlendOption.SourceAlpha;
218                                 BlendStateNorm.RenderTarget[ 0 ].DestinationBlend = SharpDX.Direct3D11.BlendOption.InverseSourceAlpha;
219                                 BlendStateNorm.RenderTarget[ 0 ].BlendOperation = SharpDX.Direct3D11.BlendOperation.Add;
220
221                                 // ブレンドステートを作成する。
222                                 テクスチャ.BlendStateNormal = new SharpDX.Direct3D11.BlendState( d3dDevice, BlendStateNorm );
223                                 //----------------
224                                 #endregion
225                                 #region " ブレンドステート(加算合成)"
226                                 //----------------
227                                 var BlendStateAdd = new SharpDX.Direct3D11.BlendStateDescription() {
228                                         AlphaToCoverageEnable = false,  // アルファマスクで透過する(するならZバッファ必須)
229                                         IndependentBlendEnable = false, // 個別設定。false なら BendStateDescription.RenderTarget[0] だけが有効で、[1~7] は無視される。
230                                 };
231                                 BlendStateAdd.RenderTarget[ 0 ].IsBlendEnabled = true; // true ならブレンディングが有効。
232                                 BlendStateAdd.RenderTarget[ 0 ].RenderTargetWriteMask = SharpDX.Direct3D11.ColorWriteMaskFlags.All;        // RGBA の書き込みマスク。
233
234                                 // アルファ値のブレンディング設定 ... 特になし
235                                 BlendStateAdd.RenderTarget[ 0 ].SourceAlphaBlend = SharpDX.Direct3D11.BlendOption.One;
236                                 BlendStateAdd.RenderTarget[ 0 ].DestinationAlphaBlend = SharpDX.Direct3D11.BlendOption.Zero;
237                                 BlendStateAdd.RenderTarget[ 0 ].AlphaBlendOperation = SharpDX.Direct3D11.BlendOperation.Add;
238
239                                 // 色値のブレンディング設定 ... 加算合成
240                                 BlendStateAdd.RenderTarget[ 0 ].SourceBlend = SharpDX.Direct3D11.BlendOption.SourceAlpha;
241                                 BlendStateAdd.RenderTarget[ 0 ].DestinationBlend = SharpDX.Direct3D11.BlendOption.One;
242                                 BlendStateAdd.RenderTarget[ 0 ].BlendOperation = SharpDX.Direct3D11.BlendOperation.Add;
243
244                                 // ブレンドステートを作成する。
245                                 テクスチャ.BlendStateAdd = new SharpDX.Direct3D11.BlendState( d3dDevice, BlendStateNorm );
246                                 //----------------
247                                 #endregion
248                                 #region " ラスタライザステート "
249                                 //----------------
250                                 var RSDesc = new SharpDX.Direct3D11.RasterizerStateDescription() {
251                                         FillMode = SharpDX.Direct3D11.FillMode.Solid,   // 普通に描画する
252                                         CullMode = SharpDX.Direct3D11.CullMode.None,    // 両面を描画する
253                                         IsFrontCounterClockwise = false,    // 時計回りが表面
254                                         DepthBias = 0,
255                                         DepthBiasClamp = 0,
256                                         SlopeScaledDepthBias = 0,
257                                         IsDepthClipEnabled = true,
258                                         IsScissorEnabled = false,
259                                         IsMultisampleEnabled = false,
260                                         IsAntialiasedLineEnabled = false,
261                                 };
262                                 テクスチャ.RasterizerState = new SharpDX.Direct3D11.RasterizerState( d3dDevice, RSDesc );
263                                 //----------------
264                                 #endregion
265                                 #region " サンプラーステート "
266                                 //----------------
267                                 var descSampler = new SharpDX.Direct3D11.SamplerStateDescription() {
268                                         Filter = SharpDX.Direct3D11.Filter.Anisotropic,
269                                         AddressU = SharpDX.Direct3D11.TextureAddressMode.Wrap,
270                                         AddressV = SharpDX.Direct3D11.TextureAddressMode.Wrap,
271                                         AddressW = SharpDX.Direct3D11.TextureAddressMode.Wrap,
272                                         MipLodBias = 0.0f,
273                                         MaximumAnisotropy = 2,
274                                         ComparisonFunction = SharpDX.Direct3D11.Comparison.Never,
275                                         BorderColor = new SharpDX.Mathematics.Interop.RawColor4( 0f, 0f, 0f, 0f ),
276                                         MinimumLod = float.MinValue,
277                                         MaximumLod = float.MaxValue,
278                                 };
279                                 テクスチャ.SamplerState = new SharpDX.Direct3D11.SamplerState( d3dDevice, descSampler );
280                                 //----------------
281                                 #endregion
282                         }
283                 }
284                 public static void 共有リソースを解放する()
285                 {
286                         FDK.Utilities.解放する( ref テクスチャ.SamplerState );
287                         FDK.Utilities.解放する( ref テクスチャ.RasterizerState );
288                         FDK.Utilities.解放する( ref テクスチャ.BlendStateAdd );
289                         FDK.Utilities.解放する( ref テクスチャ.BlendStateNormal );
290                         FDK.Utilities.解放する( ref テクスチャ.PixelShader );
291                         FDK.Utilities.解放する( ref テクスチャ.VertexShader );
292                 }
293
294                 protected static SharpDX.Direct3D11.VertexShader VertexShader = null;
295                 protected static SharpDX.Direct3D11.PixelShader PixelShader = null;
296                 protected static SharpDX.Direct3D11.BlendState BlendStateNormal = null;
297                 protected static SharpDX.Direct3D11.BlendState BlendStateAdd = null;
298                 protected static SharpDX.Direct3D11.RasterizerState RasterizerState = null;
299                 protected static SharpDX.Direct3D11.SamplerState SamplerState = null;
300         }
301 }