Saving scene to 2D texture with transparency

Hello Guys. I’m trying to render a scene and then saving it as 2D texture like a screenshot. In my test scene there is a simple model. That’s what I see:

but when I trying to save the texture in .png file it looks like emply scene:

Here is my code:

	void Start()
		scene_ = new Scene(context_); //главное - сцена

		//Здесь описываем глобальные настройки рендеринга

		Node* _pZoneAmbientNode = scene_->CreateChild("Zone");
		if (_pZoneAmbientNode != nullptr) {
			Zone* _pZoneAmbient = _pZoneAmbientNode->CreateComponent<Zone>();
			if (_pZoneAmbient != nullptr) {
				_pZoneAmbient->SetBoundingBox(BoundingBox(-2048.0f, 2048.0f));
				_pZoneAmbient->SetAmbientColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
				//_pZoneAmbient->SetFogColor(Color(1.0f, 1.0f, 1.0f, 1.0f));


		// здесь добавляем ноду для камеры и саму камеру
		/*auto cameraNode = scene_->CreateChild("MyCamera");
		cameraNode->SetPosition(Vector3(0.0f, 0.0f, -5.0f)); //положение камеры
		auto viewport = new Viewport(context_, scene_, cameraNode->GetComponent<Camera>()); //какая камера отображается на экране
		auto cameraNode = scene_->CreateChild("MyCamera");
		if (cameraNode != nullptr){
			Camera* _pCamera = cameraNode->CreateComponent<Camera>();
			if (_pCamera != nullptr) {
		auto viewport = new Viewport(context_, scene_, cameraNode->GetComponent<Camera>());
		GetSubsystem<Renderer>()->SetViewport(0, viewport);

		// здесь создаем текстуру для экспорта в приложение

		Texture2D* screenTexture = new Texture2D(context_); 
		screenTexture->SetSize(512, 512, Graphics::GetRGBFormat(), TEXTURE_RENDERTARGET);
		RenderSurface* _pRenderSurface = screenTexture->GetRenderSurface();
		if (_pRenderSurface != nullptr){
			SharedPtr<Viewport> _pViewport(new Viewport(context_, scene_, cameraNode->GetComponent<Camera>()));
			_pRenderSurface->SetViewport(0, _pViewport);

		//Здесь добавляем куб на сцену

		auto boxNode = scene_->CreateChild("MyBox");
		auto boxObject = boxNode->CreateComponent<StaticModel>();
		auto cache = GetSubsystem<ResourceCache>();
		boxNode->SetPosition(Vector3(0.0f, -50.0f, 250.0f));
		boxNode->SetRotation(Quaternion(0.0f, 90.0f, -90.0f));

		// добавляем источник освещения

		auto lightNode = scene_->CreateChild("MyLight");
		auto light = lightNode->CreateComponent<Light>();
		lightNode->SetDirection(Vector3(0.6f, -0.6f, 0.8f));

		//здесь пишем текстуру в файл (игрушечный код)


		Image* _pImage = new Image(context_);
		_pImage->SetSize(512, 512, 3);
		unsigned char* _ImageData = new unsigned char[screenTexture->GetDataSize(512, 512)];
		screenTexture->GetData(0, _ImageData); //отсюда буфер изображения можно забрать, минуя файл

		delete[] _ImageData;

Thank you !

Hi lassademus.

Saving a screenshot is easier in current master; e.g.:

Here is a bit of my code with added functionality.
‘cfg_’ is the most useful ini/config Manager by thebluefish. Here it is just setting the path from .cfg file.

bool App::SaveScreenshot(String dir /* = String::EMPTY */) const {
  if (dir.Empty()) {
    if (cfg_->Has("engine", "ScreenshotDirectory")) {
      dir = cfg_->GetString("engine", "ScreenshotDirectory", "./");
    } else {
      dir = GetSubsystem<FileSystem>()->GetProgramDir();

  String filePath(dir + "screenshot_");
  filePath += UTCTime();
  filePath += ".png";

  URHO3D_LOGINFO("Screenshot: " + filePath);

  bool dirValid = GetSubsystem<FileSystem>()->CreateDir(dir);
  if (dirValid) {

    Graphics* graphics = GetSubsystem<Graphics>();
    Image screenshot(context_);

  } else {
    URHO3D_LOGERROR("Screenshot error: invalid ScreenshotDirectory '" + dir + "'");
    return false;
  return true;

const String App::UTCTime(bool local /* = true */) const {
  std::time_t now(std::time(nullptr));
  std::tm* ptm(nullptr);
  if (local)
    ptm = std::localtime(&now);
    ptm = std::gmtime(&now);

  char buffer[32];
  std::strftime(buffer, 32, "%Y-%m-%d_%H%M%S", ptm);
  return String(buffer);


1 Like

Thanks for reply, it works, but I’m still have a problem with transparency. Is there a way to save the scene with transparent background?

The OpenGL Takescreenshot() is normally RGB (except on mobile):

Like your original function, this one reads Texture components directly – but for RGBA, passed Texture must already be RGBA (4 components) so problem is the same.

bool App::SaveTexturePNG(Texture2D* texture, const String& filePath) const {
  SharedPtr<Image> image(new Image(context_));
  image->SetSize(texture->GetWidth(), texture->GetHeight(), texture->GetComponents());

  if (texture->GetData(0, image->GetData())) {
    if (image->SavePNG(filePath)) {
      URHO3D_LOGINFO("Save texture: " + filePath);
      return true;
  } else {
    URHO3D_LOGERROR("Save texture: " + filePath + " : failed GetData().");
  return false;
1 Like