Jump to content

The problem with getting a screenshot.


photo

Recommended Posts

I'm trying to get a screenshot using the function "Viewport::renderImage2D". But the result of the picture is not like the truth. Can I see an example of getting a screenshot in C ++, and that the result is the same as using the console command "video_grab"?  Thank you in advance.

Link to comment

Hi Andrey!

Getting the exact final image produced by the render sequence is tricky but possible.
There is an abstraction called "Viewport", used by the Render, which allows subscribing to certain events while the frame is rendered.
If we subscribe to the last event triggered when the frame is finished, we can get the resulting image (we're actually free to modify it too).

With the current API Render doesn't give us access to its default viewport and returns NULL when we ask for it.
But we can always set our custom viewport with whatever settings and callbacks we want.

Please, check out the sample code below:
 

#include <UnigineApp.h>
#include <UnigineLogic.h>
#include <UnigineGame.h>
#include <UnigineViewport.h>
#include <UnigineCallback.h>
#include <UnigineRender.h>
#include <UnigineRenderState.h>

using namespace Unigine;
using namespace Unigine::Math;

class AppWorldLogic : public WorldLogic
{
public:
	AppWorldLogic() {}
	virtual ~AppWorldLogic() {}

	int init() override
	{
		viewport = Viewport::create();
		viewport->removeSkipFlags(Viewport::SKIP_VISUALIZER); // Visualizers are disabled by default for all new viewports.
		viewport->setRenderMode(Viewport::RENDER_DEPTH_GBUFFER_FINAL);
		viewport->addCallback(Viewport::CALLBACK_END, MakeCallback(this, &AppWorldLogic::screenshot_callback));
		Render::get()->setViewport(viewport);

		return 1;
	}

	int shutdown() override
	{
		Render::get()->setViewport(ViewportPtr());
		viewport.clear();

		return 1;
	}

	int update() override
	{
		if (App::get()->clearKeyState('s'))
			take_screenshot = true;

		return 1;
	}

private:
	void screenshot_callback(Renderer *renderer)
	{
		if (!take_screenshot)
			return;

		RenderState *render_state = RenderState::get();

		TexturePtr color = renderer->getTextureColor();
		TextureRenderPtr texture_render = renderer->getPostTextureRender();

		TexturePtr result = Texture::create();
		result->create2D(color->getWidth(), color->getHeight(), Texture::FORMAT_RGBA8, Texture::USAGE_RENDER);

		// Color texture that we get from the renderer is in half format (Texture::RGBA16F).
		// The simplest way to convert format is by using "render_copy_2d" material.
		render_state->saveState();
		render_state->clearStates();
		texture_render->setColorTexture(0, result);
		texture_render->enable();
		{
			Render::get()->renderPostMaterial("render_copy_2d", color);
		}
		texture_render->disable();
		texture_render->unbindColorTexture();
		render_state->restoreState();

		ImagePtr image = Image::create();
		result->getImage(image);
		if (!Render::get()->isFlipped())
			image->flipY();
		image->save("screenshot.png");

		take_screenshot = false;
	}

private:
	ViewportPtr viewport;
	bool take_screenshot = false;
};

 

Link to comment
  • 1 month later...
×
×
  • Create New...