Hey, I'm trying to render my scene to a texture. Here's the function I wrote to try to figure this out:
int DXRenderer::DrawToTexture(Window* window, ITexture& texture)
{
m_done = false;
HRESULT hRes = 0;
Camera* camera = window->GetCamera();
LPDIRECT3DTEXTURE9 dxTexture;
LPDIRECT3DSURFACE9 dxSurface;
m_d3dDevice->CreateTexture(texture.GetWidth(), texture.GetHeight(), 0, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dxTexture, NULL);
dxTexture->GetSurfaceLevel(0, &dxSurface);
m_d3dDevice->SetRenderTarget(0, dxSurface);
if(window == GetActiveWindow())
m_d3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0x99999999,1.0,0);
else
m_d3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0x88888888,1.0,0);
Matrix4 m = ~camera->GetCoordinateSystem();
m_d3dDevice->SetTransform(D3DTS_VIEW, (D3DXMATRIX*)&m);
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH( &matProjection, 45.0f * (PI/180.0f),
(float)window->GetWidth() / (float)window->GetHeight(),
camera->GetNearPlaneDistance(), camera->GetFarPlaneDistance());
m_d3dDevice->SetTransform(D3DTS_PROJECTION, &matProjection);
D3DLIGHT9 d3dLight;
ZeroMemory(&d3dLight, sizeof(d3dLight));
d3dLight.Type = D3DLIGHT_POINT;
d3dLight.Diffuse.r = 1.0f;
d3dLight.Diffuse.g = 1.0f;
d3dLight.Diffuse.b = 1.0f;
d3dLight.Ambient.r = 1.0f;
d3dLight.Ambient.g = 1.0f;
d3dLight.Ambient.b = 1.0f;
d3dLight.Specular.r = 1.0f;
d3dLight.Specular.g = 1.0f;
d3dLight.Specular.b = 1.0f;
d3dLight.Position.x = camera->GetPosition().x;
d3dLight.Position.y = camera->GetPosition().y;
d3dLight.Position.z = camera->GetPosition().z;
d3dLight.Attenuation0 = 0.5f;
d3dLight.Range = 1000.0f;
hRes = m_d3dDevice->SetLight(0, &d3dLight);
DX_ERROR(hRes);
if(m_threadSafe)
{
m_d3dDevice->BeginScene();
{
// Draw all objects.
RenderStack* renderStack = GetRenderStack();
IRenderableObj* obj = renderStack->Peek(true);
while(obj)
{
if(m_texMan.Contains(obj->GetTextureName()))
{
hRes = m_d3dDevice->SetTexture(0, m_texMan.Get(obj->GetTextureName()));
DX_ERROR(hRes);
}
else
m_d3dDevice->SetTexture(0, NULL);
Matrix4 transform = obj->GetTransform();
m_d3dDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&transform );
if(strcmp(obj->GetType(), "Triangle") == 0)
DrawTriangle((TriangleRenderObj*)obj);
else if(strcmp(obj->GetType(), "MeshSet") == 0)
DrawMesh((MeshRenderObj*)obj);
else if(strcmp(obj->GetType(), "Line") == 0)
DrawLine((LineRenderObj*)obj);
obj = renderStack->Peek();
}
}
m_d3dDevice->EndScene();
}
LPDIRECT3DTEXTURE9 dxDestTexture;
LPDIRECT3DSURFACE9 dxDestSurface;
m_d3dDevice->CreateTexture(texture.GetWidth(), texture.GetHeight(), 0, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &dxDestTexture, NULL);
dxDestTexture->GetSurfaceLevel(0, &dxDestSurface);
m_d3dDevice->GetRenderTargetData(dxSurface, dxDestSurface);
D3DLOCKED_RECT rect;
dxDestTexture->LockRect(0, &rect, NULL, 0);
for(unsigned i = 0; i < texture.GetHeight(); i++)
memcpy(texture.GetData() + (i*texture.GetWidth()), (char*)rect.pBits + (i * rect.Pitch), texture.GetWidth() * texture.GetByteType());
dxDestTexture->UnlockRect(0);
D3DXSaveSurfaceToFile(L"D:\\wtf.bmp",D3DXIFF_BMP,dxDestSurface,NULL,NULL);
dxTexture->Release();
dxSurface->Release();
dxDestTexture->Release();
dxDestSurface->Release();
m_done = true;
return 1;
}
The problem is that calling
D3DXSaveSurfaceToFile(L"D:\\wtf.bmp",D3DXIFF_BMP,dxDestSurface,NULL,NULL);
produces correct results.
for(unsigned i = 0; i < texture.GetHeight(); i++)
memcpy(texture.GetData() + (i*texture.GetWidth()), (char*)rect.pBits + (i * rect.Pitch), texture.GetWidth() * texture.GetByteType());
Does not seem to copy the same image into memory though.
Here's what was output to D:\\wtf.bmp:
and I'm rendering the texture data on the quad, in the image.
And the only last bit of information is how I'm creating my texture to be displayed. I know this is bad, but I'm creating it once per frame. So, DrawToTexture() is called, the source I'm posting below is called, and then my main render loop is called, with the updated texture applied to the quad.
case ITexture::Ax8Rx8Gx8Bx8:
szType = sizeof(char);
hRes = m_d3dDevice->CreateTexture(texture->GetWidth(), texture->GetHeight(), 0, D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &d3dTexture, NULL);
break;
}
If anyone knows why this image isn't coming out correctly on the quad, please let me know...
Thanks,
David