Sign in to follow this  
Luth

Render to Texture ... bug(?)

Recommended Posts

So I create a blank texture:
LPDIRECT3DTEXTURE9 pRenderTexture;
Direct3D::InstancePtr()->GetDevice()->CreateTexture(width,height,1,D3DUSAGE_RENDERTARGET,D3DFMT_X8R8G8B8,D3DPOOL_DEFAULT,&pRenderTexture,NULL);
return pRenderTexture;
Then I want to render a scene to it. But, to illustrate where the problem is, my "rendering" will consist of Clear()ing it white:
texture->GetSurfaceLevel(0,tempRenderSurface);
m_pD3DDevice->SetRenderTarget(0, tempRenderSurface);
m_pD3DDevice->BeginScene();
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,255,255), 1.0f, 0);
m_pD3DDevice->EndScene();
m_pD3DDevice->SetRenderTarget(0, m_pBackBuffer);
tempRenderSurface->Release();
So now I have a white texture, and I apply it to a quad object. I then render that quad object to the backbuffer as normal. My problem is that the quad doesnt get drawn. After a few hours of hunting down WHY, it turns out its because of my alpha blending:
	m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);	//source blend factor
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);	//destination blend factor
Seems that my texture is 0% opaque (100% transparent). If I switch the src/dest blend options, it draws 100% opaque (of course, everything else in the scene has its alpha completely screwed). What am I doing wrong? Why does the texture always have a 0% opaque value (even when I render a scene to the texture)?

Share this post


Link to post
Share on other sites
Is that second source snippet the actual code, line for line, word for word? I'm noticing a few things that should make it uncompilable, not to mention a memory leak.

GetSurfaceLevel(0, &tempRenderSurface)

and you're not releasing the back buffer resource after you're setting it back to be the render target, unless you do that somewhere else... which probably indicates true to me since it appears to be a class member retrieved and released somewhere else.

Share this post


Link to post
Share on other sites
No, not word for word. I tried to cut it down to size, and simplify some things to make it more readable. The actual code also includes a lot of if(FAILED()) calls as well, which makes it longer. BUT, what's a few bytes. I'll post it. I cant claim there are no memory leaks, but it does compile and run just fine.

Segments of: level.cpp
LPDIRECT3DTEXTURE9	tvTex;
tvTex = TextureManager::InstancePtr()->CreateEmptyTexture(800, 600);

Direct3D::InstancePtr()->SetRenderMode(RM_3D);

/***************
render to tvTex
***************/

LPDIRECT3DSURFACE9 pRenderSurface = NULL;
Direct3D::InstancePtr()->BeginRenderToTexture(tvTex, &pRenderSurface, D3DCOLOR_XRGB(255,255,255));
for(int i = 0; i < 5; ++i)
for(int j = 0; j < 5; ++j)
lights[i][j]->Render();
Direct3D::InstancePtr()->EndRenderToTexture(&pRenderSurface);

/****************************
Normal render to BackBuffer
****************************/

Direct3D::InstancePtr()->BeginFrame(D3DCOLOR_XRGB(255,0,0));

for(int i = 0; i < 5; ++i)
for(int j = 0; j < 5; ++j)
lights[i][j]->Render();

tv->Render(tvTex);

Direct3D::InstancePtr()->EndFrame();



Segment of: TextureManager.cpp
LPDIRECT3DTEXTURE9 TextureManager::CreateEmptyTexture(int width, int height)
{
LPDIRECT3DTEXTURE9 pRenderTexture;
Direct3D::InstancePtr()->GetDevice()->CreateTexture(width,height,1,D3DUSAGE_RENDERTARGET,D3DFMT_X8R8G8B8,D3DPOOL_DEFAULT,&pRenderTexture,NULL);
return pRenderTexture;
}



Segments of: Direct3D.cpp
bool Direct3D::BeginFrame(DWORD clearColor)
{
// start drawing stuff
if (FAILED(m_pD3DDevice->BeginScene()))
{
gamelog<<"Direct3D::BeginFrame - Failed to Begin Scene"<<endlog;
return false;
}

if(FAILED(m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clearColor, 1.0f, 0)))
{
gamelog<<"Direct3D::BeginFrame - Failed to Clear Target"<<endlog;
return false;
}

return true;
}

/************************************************
EndFrame()
************************************************/

bool Direct3D::EndFrame()
{
assert(m_pD3DDevice != NULL);
// stop drawing stuff
if (FAILED (m_pD3DDevice->EndScene()))
{
gamelog<<"Direct3D::EndFrame - Failed to EndScene"<<endlog;
return false;
}

if (FAILED (m_pD3DDevice->Present(NULL, NULL, NULL, NULL)))
{
gamelog<<"Direct3D::EndFrame - Failed to Present"<<endlog;
return false;
}

return true;
}

void Direct3D::SetRenderMode(DWORD mode)
{
switch(mode)
{
case(RM_PARTICLE):
{
m_pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE,true);
m_pD3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE,true);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
m_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
break;
}
case(RM_3D):
default:
{
m_pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE,false);
m_pD3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE,false);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); //source blend factor
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); //destination blend factor
m_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
}
}
}

bool Direct3D::BeginRenderToTexture(LPDIRECT3DTEXTURE9 texture, LPDIRECT3DSURFACE9* tempRenderSurface, DWORD clearColor)
{
// backup old data
if(FAILED(m_pD3DDevice->GetTransform(D3DTS_PROJECTION,&m_tMatOldProjection)))
{
gamelog<<"Direct3D::BeginRenderToTexture - GetTransform"<<endlog;
return false;
}

// get the surface of the texture to render to
if(FAILED(texture->GetSurfaceLevel(0,&(*tempRenderSurface))))
{
gamelog<<"Direct3D::BeginRenderToTexture - GetSurfaceLevel"<<endlog;
return false;
}

// set projection matrix for the texture dimensions
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,D3DX_PI / 4.f,1.f,1.f,100.f);
if(FAILED(m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProjection)))
{
gamelog<<"Direct3D::BeginRenderToTexture - SetTransform"<<endlog;
return false;
}

// set the render target
if(FAILED(m_pD3DDevice->SetRenderTarget(0, *tempRenderSurface)))
{
gamelog<<"Direct3D::BeginRenderToTexture - SetRenderTarget"<<endlog;
return false;
}

return BeginFrame(clearColor);
}

bool Direct3D::EndRenderToTexture(LPDIRECT3DSURFACE9* tempRenderSurface)
{
if(FAILED(m_pD3DDevice->EndScene()))
{
gamelog<<"Direct3D::EndRenderToTexture"<<endlog;
return false;
}

// restore for normal rendering
m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &m_tMatOldProjection);
if(FAILED(m_pD3DDevice->SetRenderTarget(0, m_pBackBuffer)))
{
gamelog<<"Direct3D::EndRenderToTexture - SetRenderTarget"<<endlog;
return false;
}

//cleanup render to texture thingies
(*tempRenderSurface)->Release();

return true;
}




If I turn lighting off, it draws fine. It was only when I turned lighting on that the quad didnt draw, and I was able to deduce that the texture has an alpha value of Zero, so it doesnt show up on the screen.

What it should do is set the render target to tvTex's 0 surface, clear the tvTex to white, then render a few models to it. Then it switches back to the backBuffer, renders the same objects to the backbuffer, and then render the quad with the tvTex. And it does, just fine. Except that the tvTex has alpha of Zero. (Like I said, if I tell D3D to draw with SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVSRCALPHA) and SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA), it draws fully opaque, and looks proper, though the objects rendered to back buffer are screwed up alpha-ly. So thats how I narrowed it down to just being a transparent texture, instead of normal/light/etc problems.)

Any ideas?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this