I am trying to render a birds eye view of a 3d environment to a texture and draw that texture as a HUD to represent a mini map as if it was a camera looking down at the game from above. I am pretty new at 3D programming and the DirextX API so I need help with this. From working with some examples and tutorials this is what I have but still no success.
Pretty much I don't know how to properly draw the texture onto the screen as a HUD. What happens is the engine runs the beginProjectScene() and endProjectScene() methods followed by the beginSuperImpose() method.
beginProjectScene() creates a texture to draw on, creates the appropriate view and projection matrices and back buffer as well a a new viewport and sets them after backing up the current ones. It also sets the appropriate render targets.
endProjectScene() restores the backed up matrices, viewport, back buffer.
beginSuperImpose() is supposed to draw the texture (texH) to screen.
There are some other methods called through the display device (d3dd) to D3D API methods to make this happen. But it doesn't seem to work, in fact nothing happens likely and I am not sure why. Previously before restoring the render target to the backed up back buffer in endProjectScene() the screen just went black (for obvious reasons). I believe much of my problem is working with multiple viewports and much of the concepts are relatively new and I am still trying to fully grasp.
Also when SetTexture(0, texH) call is made after restoring back buffer my white spheres turn blue.
I referred to this a bit: http://www.two-kings.de/tutorials/dxgraphics/dxgraphics16.html
Main engine loop:
int Engine::run() {
....
// update the model components
design->update(rightNow);
Viewing->update(rightNow);
audio->update(rightNow);
lighting->update();
hud->update(rightNow);
//NEW CODE FOR HUD BEGIN
// create the projection here - this part is new
display->beginProjectScene();
// draw the opaque scene objects
scene->draw(true);
// then the translucent/transparent objects
display->alphaBlendOn();
scene->draw(false);
display->alphaBlendOff();
display->endProjectScene();
//NEW CODE FOR HUD END
// draw the scene
display->beginDraw();
// draw the opaque scene objects
scene->draw(true);
// then the translucent/transparent objects
display->alphaBlendOn();
scene->draw(false);
display->alphaBlendOff();
// draw the HUD
display->beginSuperimpose();
hud->draw();
display->endDraw();
....
}
Display:
void Display::beginProjectScene() {
// create the texture COM object on which to draw
// if the texture COM object does not yet exist
//
if (!texH && FAILED(D3DXCreateTexture(d3dd, TEXTURE_WIDTH,
TEXTURE_HEIGHT, 0, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,
D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texH)))
error(L"Projection::11 Failed to create projection texture");
// get the interface to the surface for the texture - GetSurfaceLevel
// increases the reference count by 1 so we will have
// to Release the interface when done
//
if (texH && SUCCEEDED(texH->GetSurfaceLevel(0, &textureSurface))) {
// build the view matrix
//
// define position, heading, and up direction of camera and
// create a view matrix and set the view transformationf
//TEMPORTY VALUES
Vector up(0,1,0);
Vector heading(0,0,0);
Vector position(0.5,1,0.5);
Vector view(1,0,0);
// the look at point from the virtual camera
Vector lookAt = position + heading;
M开发者_高级运维atrix viewH =
::view(view, position+heading, up);
// build the projection matrix
// ...TEST VALUES
Matrix projectionProjection =
::projection(FIELD_OF_VIEW, aspect, NEAR_CLIPPING,
FAR_CLIPPING);
// back up the projection matrix and the viewport, and back buffer
d3dd->GetTransform(D3DTS_PROJECTION, &projBak);
d3dd->GetViewport(&viewportBak);
d3dd->GetRenderTarget(0, &pBackBuffer);
// associate the backbuffer with the texture surface
d3dd->SetRenderTarget(0, textureSurface);
// project the scene onto the texture
d3dd->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_ARGB(100, 100, 100, alpha), 1.0f, 0);
d3dd->BeginScene();
//d3dd->SetTexture(0, texH);
d3dd->SetTransform(D3DTS_VIEW, (D3DXMATRIX*)&viewH);
d3dd->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&projectionProjection);
// define the viewport for the texture
D3DVIEWPORT9 viewport;
viewport.X = 0;
viewport.Y = 0;
viewport.Width = TEXTURE_WIDTH;
viewport.Height = TEXTURE_HEIGHT;
viewport.MinZ = 0.0f;
viewport.MaxZ = 1.0f;
d3dd->SetViewport(&viewport);
//d3dd->EndScene();
}
}
void Display::endProjectScene() {
d3dd->SetRenderTarget(0, pBackBuffer);
d3dd->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_ARGB(100, 100, 100, alpha), 1.0f, 0);
//d3dd->BeginScene();
//d3dd->SetTexture(0, texH);
// restore the projection and viewport
d3dd->SetTransform(D3DTS_PROJECTION, &projBak);
d3dd->SetViewport(&viewportBak);
d3dd->EndScene();
// release the backbuffer associated with the texture
textureSurface->Release();
pBackBuffer->Release();
//texH->Release();
}
void Display::beginSuperimpose() {
// prepare to draw the hud
//
if (spriteManager_){
// start the sprite manager
spriteManager_->Begin(D3DXSPRITE_ALPHABLEND);
//NEW CODE FOR HUD
Vector topRight(width() * 0.01f, height() * 0.01f, 0);
spriteManager_->Draw(texH, NULL, NULL, (D3DXVECTOR3*)&topRight,
D3DCOLOR_RGBA(SPRITEH_R, SPRITEH_G, SPRITEH_B, 1));
}
}
Try changing , 1 to , 255 in the call to Draw. D3DCOLOR_RGBA takes values in the range 0 to 255. A value of 1 for alpha is transparent, nearly.
Change
Vector topRight(width() * 0.01f, height() * 0.01f, 0);
to:
Vector topRight(0.5f, 0.5f, 0);
And see if it renders. This ought to display the sprite with the upper left corner starting 3/4 of the ay across the screen and 1/4 of the way down it.
I suspect that your width calculation is putting it off screen. The DirectX render space goes from -1 to 1 in x and y. So if your width is 1024 then multiplying by 0.01f will result in a value of 1.024 which is off the right hand side of the screen.
You should draw your HUD AFTER you drawed the scene, otherwise the scene will overlay the HUD.
精彩评论