DirectX9 レンダリングターゲット
レンダリングターゲット思った以上にめんどい
とりあえずのクラス化
#define SAFE_RELEASE(a) { if(a) { (a)->Release(); (a)=NULL; } } // レンダリングターゲット用 class RenderTarget{ private: LPDIRECT3DTEXTURE9 texture_; LPDIRECT3DSURFACE9 surface_; LPDIRECT3DSURFACE9 depth_; D3DVIEWPORT9 viewport_; DWORD width_; DWORD height_; public: RenderTarget() : texture_(NULL), surface_(NULL), depth_(NULL), width_(0), height_(0){} ~RenderTarget(){ SAFE_RELEASE(surface_); SAFE_RELEASE(depth_); SAFE_RELEASE(texture_); } bool CreateRenderTarget(LPDIRECT3DDEVICE9 device, DWORD width, DWORD height){ width_ = width; height_ = height; if(!CreateTexture_(device)) return false; if(!CreateDepth_(device)) return false; if(!CreateSurface_(device) return false; CreateViewport_(); return true; } void SetRenderTarget(LPDIRECT3DDEVICE9 device){ device->SetRenderTarget(0, surface_); device->SetDepthStencilSurface(depth_); device->SetViewport(&viewport_); } LPDIRECT3DTEXTURE9 GetTexture(){ return texture_; } private: bool CreateTexture_(LPDIRECT3DDEVICE9 device){ if(FAILED(device->CreateTexture(width_, height_, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture_, NULL))){ return false; } return true; } bool CreateDepth_(LPDIRECT3DDEVICE9 device){ if(FAILED(device->CreateDepthStencilSurface(width_, height_, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, TRUE, &depth_, NULL))){ return false; } return true; } bool CreateSurface_(LPDIRECT3DDEVICE9 device){ if(FAILED(texture_->GetSufaceLevel(0, &surface_))){ return false; } return true; } void CreateViewport_(){ viewport_.X = 0; viewport_.Y = 0; viewport_.Width = width_; viewport_.Height = height_; viewport_.MinZ = 0.0f; viewport_.MaxZ = 1.0f; } }; // バックバッファ保存用 class BackBuffer{ private: D3DVIEWPORT9 viewport_; LPDIRECTSURFACE9 surface_; LPDIRECTSURFACE9 depth_; public: explicit BackBuffer(LPDIRECT3DDEVICE9 device){ device->GetViewport(&viewport_); device->GetRenderTarget(0, &surface_); device->GetDepthStencilSurface(&depth_); } ~BackBuffer(){ SAFE_RELEASE(surface_); SAFE_RELEASE(depth_); } void SetRenderTarget(LPDIRECT3DDEVICE9 device){ device->SetRenderTarget(0, surface_); device->SetDepthStencilSurface(depth_); device->SetViewport(&viewport_); } }; void Draw(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 texture, int dx, int dy, int dw, int dh){ // --------------------------------------------------------------------------------------- // バックバッファのデータをレンダリングターゲットを保存しないと、描画できなくなるので保存。 // --------------------------------------------------------------------------------------- BackBuffer back(device); // --------------------------------------------------------------------------------------- // あらかじめ作成したレンダリングターゲットに切り替える // --------------------------------------------------------------------------------------- RenderTarget render; render.CreateRenderTarget(device, dw, dh); render.SetRenderTarget(device); device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0); // --------------------------------------------------------------------------------------- // 座標変換 // --------------------------------------------------------------------------------------- const float screen_width = static_cast<float>(SCREEN_WIDTH); const float screen_height = static_cast<float>(SCREEN_HEIGHT); D3DXMATRIX proj( 2/screen_w, 0.0f, 0.0f, 0.0f, 0.0f, -2/screen_h, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f); device->SetTransform(D3DTS_PROJECTION, &proj); // --------------------------------------------------------------------------------------- // 描画 // --------------------------------------------------------------------------------------- device->SetTexture(0, texture); const flost x = (float)dx; const float y = (float)dy; const float w = (float)dw; const float h = (float)dh; struct MyVertex{ float x, y, z; DWORD color; float u, v; } vtx[] = { x, y, 0.0f, ~0, 0.0f, 0.0f, x + w, y, 0.0f, ~0, 1.0f, 0.0f, x, y + h, 0.0f, ~0, 0.0f, 1.0f, x + w, y + h, 0.0f, ~0, 1.0f, 1.0f, }; device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vtx, sizeof(MyVertex)); // --------------------------------------------------------------------------------------- // バックバッファに切り替え 描画 // --------------------------------------------------------------------------------------- back.SetRenderTarget(device); device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0); device->SetTexture(0, render.GetTexture()); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vtx, sizeof(MyVertx)); }
さらにシェーダ使ってみた版
// shader.fx float4x4 mWVP; texture Tex; sampler Samp = sampler_state{ Texture = <Tex>; AddressU = Border; AddressV = Border; }; struct VS_OUTPUT{ float4 Pos : POSITION; float2 Tex : TEXCOORD0; }; //----------------------------------------------------------------- // vertex_shader //----------------------------------------------------------------- VS_OUTPUT vs_main(float4 Pos : POSITION, float2 Tex : TEXCOORD){ VS_OUTPUT Out = (VS_OUTPUT)0; Out.Pos = mul(Pos, mWVP); Out.Tex = Tex; return Out; } //----------------------------------------------------------------- // pixel_shader 今回簡単なサンプルでグレースケールの適当版 //----------------------------------------------------------------- float4 ps_gray(float2 Tex : TEXCOORD0) : COLOR0 { float4 color = tex2D(Samp, Tex); return (color.r + color.g + color.b) * 0.3333f; } //----------------------------------------------------------------- // テクニック //----------------------------------------------------------------- technique TShader{ pass p0{ VertexShader = compile vs_3_0 vs_main(); PixelShader = compile ps_3_0 ps_gray(); } }
// main.cpp void Draw(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 texture, int dx, int dy, int dw, int dh){ BackBuffer back(device); TRenderTarget render; render.CreateRenderTarget(device, dw, dh); render.SetRenderTarget(device); shader_.Clear(device, ARGB(255, 0, 0, 0)); const float screen_w = static_cast<float>(SCREEN_WIDTH); const float screen_h = static_cast<float>(SCREEN_HEIGHT); D3DXMATRIX proj( 2/screen_w, 0.0f, 0.0f, 0.0f, 0.0f, -2/screen_h, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f); device->SetTransform(D3DTS_PROJECTION, &proj); D3DXMATRIX& world = proj; effect_->SetMatrix("mWVP", &world); effect_->SetTexture("Tex", texture); const float x = (float)dx; const float y = (float)dy; const float w = (float)dw; const float h = (float)dh; struct MyVertex{ float x, y, z; DWORD color; float u, v; } vtx[] = { x, y, 0.0f, ~0, 0.0f, 0.0f, x + w, y, 0.0f, ~0, 1.0f, 0.0f, x, y + h, 0.0f, ~0, 0.0f, 1.0f, x + w, y + h, 0.0f, ~0, 1.0f, 1.0f, }; // シェーダ描画 レンダリングターゲット effect_->SetTechnique("TShader"); effect_->Begin(NULL, 0); effect_->BeginPass(0); device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vtx, sizeof(MyVertex) ); effect_->EndPass(); effect_->End(); // バックバッファ back.SetRenderTarget(device); device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0); device->SetTexture(0, render.GetTexture()); device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vtx, sizeof(MyVertex) ); }
感覚で書いてるから間違ってるかも。
質問受け付けてないです!! がんばって解決してね!