
レンダリングテクスチャ
★ 1.はじめに…
今回は,描画結果をテクスチャとして使用するレンダリングテクスチャをやってみます。


★ 2.概要
OpenGLのときはFrameBufferObjectなりPixelBufferObjectを用意しました。XNA Game Studioのときはレンダーターゲットを用意しておき,描画した後にGetTexture()メソッドで描画した結果を取得しました。DirectX 10からはレンダーターゲットビュー作成時にシェーダリソースビューを一緒に作成しておき,バインドさせておけばよいそうです。
処理の流れですが下記のようになります。
あとは,下記のように最初に描画する際にレンダーターゲットに上記で生成したレンダーターゲットを指定し,普通に描画してやります。次に,描画が終わったらPSSetShaderResource()メソッドあたりで,シェーダに描画結果を転送してやればOKです。シェーダ側では普通のテクスチャと同じように処理してやります。
今回は,レンダリングテクスチャをやりました。これでようやく色々とできそうです。
処理の流れですが下記のようになります。
(1)2次元テクスチャ作成。BindFlagsにレンダーターゲットとシェーダリソースビューを指定おく。 (2)レンダーターゲットビューを生成。リソースには(1)で作成した2次元テクスチャを指定。 (3)シェーダリソースビューを作成。同じくリソースには(1)で作成した2次元テクスチャを指定。 (4)描画する際に,作成したレンダーターゲットビューを設定。 (5)描画し終わったら,シェーダリソースビューをシェーダに転送。実際のコードを見ていきましょう。
00178: // 2次元テクスチャの設定
00179: D3D11_TEXTURE2D_DESC texDesc;
00180: memset( &texDesc, 0, sizeof( texDesc ) );
00181: texDesc.Usage = D3D11_USAGE_DEFAULT;
00182: texDesc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
00183: texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
00184: texDesc.Width = pDesc->Width;
00185: texDesc.Height = pDesc->Height;
00186: texDesc.CPUAccessFlags = 0;
00187: texDesc.MipLevels = 1;
00188: texDesc.ArraySize = 1;
00189: texDesc.SampleDesc.Count = 1;
00190: texDesc.SampleDesc.Quality = 0;
00191:
00192: // 2次元テクスチャの生成
00193: hr = pDevice->CreateTexture2D( &texDesc, NULL, &mpTex );
00194: if ( FAILED( hr ) )
00195: {
00196: ELOG( "Error : ID3D11Device::CreateTexture2D() Failed." );
00197: return false;
00198: }
00199:
00200: // レンダーターゲットビューの設定
00201: D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
00202: memset( &rtvDesc, 0, sizeof( rtvDesc ) );
00203: rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
00204: rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
00205:
00206: // レンダーターゲットビューの生成
00207: hr = pDevice->CreateRenderTargetView( mpTex, &rtvDesc, &mpRTV );
00208: if ( FAILED( hr ) )
00209: {
00210: ELOG( "Error : ID3D11Device::CreateRenderTargetView() Failed." );
00211: return false;
00212: }
00213:
00214: // シェーダリソースビューの設定
00215: D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
00216: memset( &srvDesc, 0, sizeof( srvDesc ) );
00217: srvDesc.Format = rtvDesc.Format;
00218: srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
00219: srvDesc.Texture2D.MipLevels = 1;
00220:
00221: // シェーダリソースビューの生成
00222: hr = pDevice->CreateShaderResourceView( mpTex, &srvDesc, &mpSRV );
00223: if ( FAILED( hr ) )
00224: {
00225: ELOG( "Error : ID3D11Device::CreateShaderResourceView() Failed." );
00226: return false;
00227: }
00228:
00229: // サンプラステートの設定
00230: D3D11_SAMPLER_DESC smpDesc;
00231: memset( &smpDesc, 0, sizeof( smpDesc ) );
00232: smpDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
00233: smpDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
00234: smpDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
00235: smpDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
00236: smpDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
00237: smpDesc.MinLOD = 0;
00238: smpDesc.MaxLOD = D3D11_FLOAT32_MAX;
00239:
00240: // サンプラステート生成
00241: hr = pDevice->CreateSamplerState( &smpDesc, &mpSmp );
00242: if ( FAILED( hr ) )
00243: {
00244: ELOG( "Error : ID3D11Device::CreateSamplerState() Failed." );
00245: return false;
00246: }
言ったまんまの処理です。まずテクスチャを生成して,これをレンダーターゲットビューとシェーダリソースビューに設定します。当然ながら,シェーダでサンプルするときにサンプラステートを使うので,サンプラステートも生成してしまっています。あとは,下記のように最初に描画する際にレンダーターゲットに上記で生成したレンダーターゲットを指定し,普通に描画してやります。次に,描画が終わったらPSSetShaderResource()メソッドあたりで,シェーダに描画結果を転送してやればOKです。シェーダ側では普通のテクスチャと同じように処理してやります。
00333: //-----------------------------------------------------------------------
00334: //! @brief 描画処理
00335: //-----------------------------------------------------------------------
00336: void SampleRenderer::OnRender
00337: (
00338: ID3D11Device* pDevice,
00339: ID3D11DeviceContext* pImmediateContext,
00340: double time,
00341: float elapsedTime
00342: )
00343: {
00344: //===================================================================
00345: // テクスチャに描画
00346: //===================================================================
00347:
00348: // カメラ設定
00349: D3DXVECTOR3 cameraPosition = D3DXVECTOR3( 0.0f, 2.5f, 5.0f );
00350: D3DXVECTOR3 cameraTarget = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
00351: D3DXVECTOR3 cameraUpVector = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
00352:
00353: // ビュー行列計算
00354: D3DXMatrixLookAtLH( &mView, &cameraPosition, &cameraTarget, &cameraUpVector );
00355:
00356: // 視線ベクトル計算
00357: mViewDir = cameraTarget - cameraPosition;
00358:
00359: // デフォルトの深度・ステンシルビューを取得
00360: ID3D11DepthStencilView* pDSV = DemoApp::GetInstance()->GetDefaultDepthStencilView();
00361:
00362: float clearColor[ 4 ] = { 0.3f, 0.3f, 1.0f, 1.0f };
00363: // 自前のレンダーターゲットビューに切り替え
00364: pImmediateContext->OMSetRenderTargets( 1, &mpRTV, pDSV );
00365: pImmediateContext->ClearRenderTargetView( mpRTV, clearColor );
00366: pImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0f, 0 );
00367:
00368: // デフォルトシェーダを取得
00369: ID3D11VertexShader *pVS = ModelUtil::GetDefaultVertexShader();
00370: ID3D11PixelShader *pPS = ModelUtil::GetDefaultPixelShader();
00371:
00372: // シェーダを設定
00373: pImmediateContext->VSSetShader( pVS, NULL, 0 );
00374: pImmediateContext->PSSetShader( pPS, NULL, 0 );
00375:
00376: // 定数バッファ設定
00377: D3DXMatrixIdentity( &mWorld );
00378: ModelUtil::SetMatrix( pImmediateContext, mWorld, mView, mProjection );
00379: ModelUtil::SetVector( pImmediateContext, mLightDir, mViewDir );
00380:
00381: // モデルを描画
00382: mSaturn.Draw( pImmediateContext );
00383:
00384: // 平行移動行列を計算
00385: D3DXMATRIX translate;
00386: D3DXMatrixTranslation( &translate, 0.0f, -1.0f, 0.0f );
00387:
00388: // ワールド行列を設定
00389: mWorld = translate;
00390:
00391: // 行列転送
00392: ModelUtil::SetMatrix( pImmediateContext, mWorld, mView, mProjection );
00393:
00394: // 地面を描画
00395: mGround.Draw( pImmediateContext );
00396:
00397: //===================================================================
00398: // 通常描画
00399: //===================================================================
00400:
00401: // カメラ設定
00402: cameraPosition = D3DXVECTOR3( 0.0f, 2.5f, -5.0f );
00403: cameraTarget = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
00404: cameraUpVector = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
00405:
00406: // ビュー行列計算
00407: D3DXMatrixLookAtLH( &mView, &cameraPosition, &cameraTarget, &cameraUpVector );
00408:
00409: // 視線ベクトル計算
00410: mViewDir = cameraTarget - cameraPosition;
00411:
00412: // デフォルトのレンダーターゲットビューを取得
00413: ID3D11RenderTargetView* pRTV = DemoApp::GetInstance()->GetDefaultRenderTargetView();
00414:
00415: // デフォルトのレンダーターゲットビューに切り替え
00416: pImmediateContext->OMSetRenderTargets( 1, &pRTV, pDSV );
00417: pImmediateContext->ClearRenderTargetView( pRTV, DemoApp::GetInstance()->GetDefaultClearColor() );
00418: pImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0f, 0 );
00419:
00420: // シェーダを設定
00421: pImmediateContext->VSSetShader( pVS, NULL, 0 );
00422: pImmediateContext->PSSetShader( pPS, NULL, 0 );
00423:
00424: // 定数バッファ設定
00425: D3DXMatrixIdentity( &mWorld );
00426: ModelUtil::SetMatrix( pImmediateContext, mWorld, mView, mProjection );
00427: ModelUtil::SetVector( pImmediateContext, mLightDir, mViewDir );
00428:
00429: // モデルを描画
00430: mSaturn.Draw( pImmediateContext );
00431:
00432: // ワールド行列を設定
00433: mWorld = translate;
00434:
00435: // 行列転送
00436: ModelUtil::SetMatrix( pImmediateContext, mWorld, mView, mProjection );
00437:
00438: // 地面を描画
00439: mGround.Draw( pImmediateContext );
00440:
00441: //===================================================================
00442: // レンダリングテクスチャの描画
00443: //===================================================================
00444:
00445: // デバッグ描画シェーダを設定
00446: pImmediateContext->VSSetShader( mpQuadVS, NULL, 0 );
00447: pImmediateContext->PSSetShader( mpQuadPS, NULL, 0 );
00448:
00449: // レンダリングテクスチャを設定
00450: pImmediateContext->PSSetShaderResources( 0, 1, &mpSRV );
00451: pImmediateContext->PSSetSamplers( 0, 1, &mpSmp );
00452:
00453: // 頂点バッファを設定
00454: uint32_t offset = 0;
00455: pImmediateContext->IASetVertexBuffers( 0, 1, &mpQuadVB, &mQuadStride, &offset );
00456: pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
00457:
00458: // 矩形描画
00459: pImmediateContext->Draw( 6, 0 );
00460:
00461: }
そんなわけで,いちいちGetTexture()みたいなことはしなくてよいみたいです。今回は,レンダリングテクスチャをやりました。これでようやく色々とできそうです。
★ Download
本ソースコードおよびプログラムを使用したことによる如何なる損害も製作者は責任を負いません。
本ソースコードおよびプログラムは自己責任でご使用ください。
プログラムの作成にはMicrosoft Visual Studio 2008 SP1 Professional, Microsoft DirectX SDK (June 2010)を用いています。
本ソースコードおよびプログラムは自己責任でご使用ください。
プログラムの作成にはMicrosoft Visual Studio 2008 SP1 Professional, Microsoft DirectX SDK (June 2010)を用いています。
