Jump to content

Rendering the main window to an image. Help?


photo

Recommended Posts

I cannot figure out how to render the current window to an Image or ImagePtr object. Does anyone have an example code snipped that works?

 

I have tried doing it with the console command "video_grab" but that isn't fast enough. I've also tried the Viewport object and the Renderer object's API.


 

   ImagePtr image = Image::create();

    image->create2D(1024, 576, Image::FORMAT_RGBA8, 1, 1);

    PlayerSpectatorPtr player = PlayerSpectator::create();
    player->setPosition(Math::Vec3(0, 0, 2.0f));

    CameraPtr camera = player->getCamera()->clone();

    ViewportPtr viewport = Viewport::create();


    Render *render = Unigine::Render::get();

    render->setViewport(viewport);

    image->create2D(1024, 576, Image::FORMAT_RGBA8, 1, 1, 1);
    
    render->renderImage2D(camera, image, 0); 

 

The last line cases a crash of the application. I am using the C++ interface on the 2.5 SDK.

Link to comment

Hi Silent,

Thanks for the pointer. I have the samples from previous version downloaded in the SDK browser. How can I force an update of the samples to see the new ones?

 

Also, I'm not trying to disable the main window, I just want the pixels out of it in an Image object. It does seem that that should be simpler than it appears to be.

Link to comment

To enable new samples you need to make 2.5 SDK as default in SDKs tab.

If you can describe your use case in more details (what do you want to implement), we probably can suggest you different approach. But that one from samples should be already enough.

Thanks!

How to submit a good bug report
---
FTP server for test scenes and user uploads:

Link to comment

Thank you for the pointers. I see the 2.5 samples now. I had 2.4.1 set as my default which was the issue.

 

The use-case is that I'm porting UnigineScript to C++. My UnigineScript routine is below. It stores 30 screenshots in an array of Image. I then play them back as an "action replay" in a race by creating a WidgetSprite and calling setImage() on it to display the images in sequence. 

 

void buffer_and_playback() {

  Image images[0];

  Player play = node_cast(engine.editor.getNodeByName("finishline_cam"));
  Camera cam = play.getCamera();
  Viewport vp = new Viewport();
  vp.setSkipFlags(VIEWPORT_SKIP_VELOCITY_BUFFER);


  forloop(int i = 0; 30) {
    images.append(new Image());
    vp.renderImage2D(cam, images[i]);
    busy_sleep(1.0f/FPS);
  }
 ...

 

The closest I have got so far is pasted below. This does render out an image to the PNG but I think it is done so before the sky is drawn and before anti-aliasing is done as they appear to be missing.

 

void testit() {
    Log::message("Button pressed\n");

    int width = 1024;
    int height = 576;


    Render *render = Render::get();
    
    // Below line returns null. Is this a bug?
    //ViewportPtr viewport = render->getViewport();
    
    ViewportPtr viewport = Viewport::create();
    viewport->setRenderMode(Viewport::RENDER_DEPTH_GBUFFER_FINAL);
    viewport->setSkipFlags(0);
    
    PlayerPtr player = Game::get()->getPlayer();
    CameraPtr camera = player->getCamera();
    ImagePtr image = Image::create();

    // Must be called before renderImage2D
    viewport->render(camera);
    
    image->create2D(width, height, 1, 1, 1);
    
    viewport->renderImage2D(camera, image, width, height, 0);
    
    image->save("test-image.png");

 

I have also tried the Texture interface rather than the Image interface and it gives the same result. The image produced form the above code is below. The darkness is fine as the quadratic exposure isn't going to be in a viewport but note the sky is missing and it's not anti-aliased as you can see if you zoom in.

 

test-image.thumb.png.d3e7307e32a81ac71662f85333894362.png

 

Am I going about this in the right way, or is there a different route I should be trying? Getting a screenshot of the final buffer sent to the screen seems like it should be easier than it appears.

 

 

Link to comment

Hi Angus,

I've attached a C++ example of a simple video grabber which uses the Viewport::RenderImage2D method. Please check it out, the source files include necessary comments. Just create a new C++ project and replace AppWorldLogic.* source files with the ones attached.

TAA and exposure issues are associated with the fact that both of these features use series of subsequent frames, so we have to call Viewport::RenderImage2D each frame. You should notice TAA and adaptive exposure warm-up at the beginning of the playback.

In order to see the sky the image should be converted to the RGB8 format.

image->convertToFormat(Unigine::Image::FORMAT_RGB8);

Hope this helps!

Thanks!

AppWorldLogic.cpp

AppWorldLogic.h

Link to comment
×
×
  • Create New...