简体   繁体   中英

Render to texture for mini map, dirextX

替代文字

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 aa 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;
    Matrix 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));
 }
}

绘制场景后应绘制HUD,否则场景将覆盖HUD。

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM