OMG Medo, you still don't get it. I don't know how to simplify it more.
There is something confuse me, I have already drawn everything when I called RenderScene();
Yes but you draw it to these surfaces:
void Render()
{
...
device->SetRenderTarget(0, DepthSurface);
device->SetRenderTarget(1, ColorSurface);
// -- Render the scene
HRESULT hr = device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
assert(SUCCEEDED(hr));
device->BeginScene();
RenderScene();
...
}
every draw call draws to the last render target set by SetRenderTarget function, but backbuffer surface is still empty so there is nothing to display on screen.
HRESULT hr = D3DXSaveTextureToFile("depth.png", D3DXIFF_PNG, DepthTex, NULL);
Be careful with this function:
1. Dont call it when texture you are about to save has its surface still bound as render target
2. Note the format of the texture you are about the save, as far as i know PNG cannot hold floating point texture, so better to use DDS as it is far more capable.
device->SetRenderTarget(0, ColorSurface); // *** Switch to color surface ***
This is not backbuffer surface so still nothing to display on screen!
Unbird suggested to draw "fullscreen quad" as last step.
EDIT:
Since i doubt that you will find decent tutorial for "fullscreen quad", and i wish that someone helped me at beginning like i do for you now, here is simple example to play with:
cpp
class FSQuad
{
private:
LPDIRECT3DDEVICE9 device;
LPDIRECT3DVERTEXBUFFER9 vBuffer;
LPDIRECT3DINDEXBUFFER9 iBuffer;
LPDIRECT3DVERTEXDECLARATION9 vDeclaration;
struct FS_VERTEX
{
D3DXVECTOR3 position;
D3DXVECTOR2 texcoord;
};
public:
FSQuad(LPDIRECT3DDEVICE9 _device)
: device(_device), iBuffer(nullptr), vBuffer(nullptr), vDeclaration(nullptr)
{
device->AddRef();
}
~FSQuad()
{
if(nullptr != device)
{
device->Release();
device = nullptr;
}
if(nullptr != iBuffer)
{
iBuffer->Release();
iBuffer = nullptr;
}
if(nullptr != vBuffer)
{
vBuffer->Release();
vBuffer = nullptr;
}
if(nullptr != vDeclaration)
{
vDeclaration->Release();
vDeclaration = nullptr;
}
}
bool init()
{
D3DVERTEXELEMENT9 fsVertexElements[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
HRESULT hr = D3D_OK;
hr = device->CreateVertexBuffer(sizeof(FS_VERTEX) * 4, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &vBuffer, nullptr);
if(FAILED(hr))
{
MessageBox(0, "Failed to create FS VB!", 0, 0);
return false;
}
hr = device->CreateIndexBuffer(sizeof(USHORT) * 6, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &iBuffer, nullptr);
if(FAILED(hr))
{
MessageBox(0, "Failed to create FS IB!", 0, 0);
return false;
}
hr = device->CreateVertexDeclaration(fsVertexElements, &vDeclaration);
if(FAILED(hr))
{
MessageBox(0, "Failed to create FS VD!", 0, 0);
return false;
}
float c = 1.0f;
float z = 1.0f;
FS_VERTEX* pVertices = nullptr;
vBuffer->Lock(0, 0, (void**)&pVertices, 0);
pVertices[0].position = D3DXVECTOR3( -c, c, z); pVertices[0].texcoord = D3DXVECTOR2(0.0f, 0.0f);
pVertices[1].position = D3DXVECTOR3( c, c, z); pVertices[1].texcoord = D3DXVECTOR2(1.0f, 0.0f);
pVertices[2].position = D3DXVECTOR3( c, -c, z); pVertices[2].texcoord = D3DXVECTOR2(1.0f, 1.0f);
pVertices[3].position = D3DXVECTOR3( -c, -c, z); pVertices[3].texcoord = D3DXVECTOR2(0.0f, 1.0f);
vBuffer->Unlock();
USHORT* pIndices = nullptr;
iBuffer->Lock(0, 0, (void**)&pIndices, 0);
pIndices[0] = 0;
pIndices[1] = 1;
pIndices[2] = 2;
pIndices[3] = 0;
pIndices[4] = 2;
pIndices[5] = 3;
iBuffer->Unlock();
return true;
}
void draw()
{
device->SetStreamSource(0, vBuffer, 0, sizeof(FS_VERTEX));
device->SetIndices(iBuffer);
device->SetVertexDeclaration(vDeclaration);
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);
}
};
then you have shader like this, here you could use your depth & color texture:
float4 ScreenParams; // xy width/height of screen
struct VERTEX
{
float3 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;
};
struct PS_OUTPUT
{
float4 Color : COLOR0;
};
void VertexProgram(in VERTEX IN, out VS_OUTPUT OUT)
{
float2 texelOffset = float2(-1.0f / ScreenParams.x, 1.0f / ScreenParams.y);
float2 result = IN.Position.xy;
result.xy += texelOffset;
OUT.Position.x = result.x;
OUT.Position.y = result.y;
OUT.Position.z = 1.0f;
OUT.Position.w = 1.0f;
OUT.TexCoord0 = float2(0.5f, -0.5f) * IN.Position.xy + 0.5f.xx;
}
void PixelProgram(in VS_OUTPUT IN, out PS_OUTPUT OUT)
{
...
OUT.Color = ...;
}