Rendering textures to textures?

Before anyone asks, yes, I have checked Google.

I’ve been searching for a way to render a texture onto another texture. My problem is I need to be able to draw things to particular layers, and textures seem to only be able to draw directly to the screen or to a viewport. Whenever I look online, I just find links that lead back to the wiki page on rendering a texture to the screen. Is it possible to render a texture onto another texture without having to use surfaces and then converting to textures (which kinda defeats the point of textures in the first place, but I’ve actually had people tell me to do that).

RenderTarget. https://wiki.libsdl.org/SDL_SetRenderTarget

I made a small program which are rendering a image texture (‘pTexture’) onto another texture (‘pTargetTexture’).

Code:

#include “SDL.h”

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

SDL_Window* pWindow = NULL;
SDL_Renderer* pRenderer = NULL;

SDL_Texture* pTexture = NULL;
SDL_Texture* pTargetTexture = NULL;

SDL_Event Event;

bool Running = true;

int main(int argc, char* argv[])
{
// Initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
// If there was a problem initializing SDL
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, “Couldn’t initialize SDL: %s\n”, SDL_GetError());
}

// If SDL was successfully initialized
else
{
	// Create the window
	pWindow = SDL_CreateWindow("Render To Texture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);

	if(pWindow)
	{
		// Create the renderer with the render to texture option enabled
		pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

		if(pRenderer)
		{
			// Set the render draw color
			SDL_SetRenderDrawColor(pRenderer, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);


			SDL_Surface* pSurface = NULL;
			pSurface = SDL_LoadBMP("Image.bmp");

			if(pSurface)
			{
				// Create the image texture
				pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
			
				// Destroy the temporary surface
				SDL_FreeSurface(pSurface);
			}


			// Create the target texture with the render target option enabled
			pTargetTexture = SDL_CreateTexture(pRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, WINDOW_WIDTH, WINDOW_HEIGHT);
		}
	}
}

while(Running)
{
	while(SDL_PollEvent(&Event))
	{
		if(Event.type == SDL_QUIT)
		{
			Running = false;
			break;
		}
	}

	// Clear the current render target
	SDL_RenderClear(pRenderer);

	// Set the target texture as the current render target
	SDL_SetRenderTarget(pRenderer, pTargetTexture);
	
	if(pTexture)
	{
		SDL_Rect TextureQuad = {0, 0, 0, 0};
		
		SDL_QueryTexture(pTexture, NULL, NULL, &TextureQuad.w, &TextureQuad.h);

		TextureQuad.x = (WINDOW_WIDTH - TextureQuad.w) / 2;
		TextureQuad.y = (WINDOW_HEIGHT - TextureQuad.h) / 2;

		// Render the image texture in the middle of the window (onto the target texture)
		SDL_RenderCopy(pRenderer, pTexture, NULL, &TextureQuad);
	}

	// Reset the render target
	SDL_SetRenderTarget(pRenderer, NULL);

	// Render the target texture
	if(pTargetTexture)
		SDL_RenderCopy(pRenderer, pTargetTexture, NULL, NULL);

	// Update the screen
	SDL_RenderPresent(pRenderer);
}

// Destroy the target texture
if(pTargetTexture)
	SDL_DestroyTexture(pTargetTexture);

// Destroy the image texture
if(pTexture)
	SDL_DestroyTexture(pTexture);

// Destroy the renderer
SDL_DestroyRenderer(pRenderer);
pRenderer = NULL;

// Destroy the window
SDL_DestroyWindow(pWindow);
pWindow = NULL;

// Quit SDL
SDL_Quit();

return 0;

}

I’ve made a small code example explaining how to render a image texture (‘pTexture’) onto another texture (‘pTargetTexture’). Code below.

Code:

#include “SDL.h”

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

SDL_Window* pWindow = NULL;
SDL_Renderer* pRenderer = NULL;

SDL_Texture* pTexture = NULL;
SDL_Texture* pTargetTexture = NULL;

SDL_Event Event;

bool Running = true;

int main(int argc, char* argv[])
{
// Initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
// If there was a problem initializing SDL
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, “Couldn’t initialize SDL: %s\n”, SDL_GetError());
}

// If SDL was successfully initialized
else
{
	// Create the window
	pWindow = SDL_CreateWindow("Render To Texture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);

	if(pWindow)
	{
		// Create the renderer with the render to texture option enabled
		pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

		if(pRenderer)
		{
			// Set the render draw color
			SDL_SetRenderDrawColor(pRenderer, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);


			SDL_Surface* pSurface = NULL;
			pSurface = SDL_LoadBMP("Image.bmp");

			if(pSurface)
			{
				// Create the image texture
				pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
			
				// Destroy the temporary surface
				SDL_FreeSurface(pSurface);
			}


			// Create the target texture with the render target option enabled
			pTargetTexture = SDL_CreateTexture(pRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, WINDOW_WIDTH, WINDOW_HEIGHT);
		}
	}
}

while(Running)
{
	while(SDL_PollEvent(&Event))
	{
		if(Event.type == SDL_QUIT)
		{
			Running = false;
			break;
		}
	}

	// Clear the current render target
	SDL_RenderClear(pRenderer);

	// Set the target texture as the current render target
	SDL_SetRenderTarget(pRenderer, pTargetTexture);
	
	if(pTexture)
	{
		SDL_Rect TextureQuad = {0, 0, 0, 0};
		
		SDL_QueryTexture(pTexture, NULL, NULL, &TextureQuad.w, &TextureQuad.h);

		TextureQuad.x = (WINDOW_WIDTH - TextureQuad.w) / 2;
		TextureQuad.y = (WINDOW_HEIGHT - TextureQuad.h) / 2;

		// Render the image texture in the middle of the window (onto the target texture)
		SDL_RenderCopy(pRenderer, pTexture, NULL, &TextureQuad);
	}

	// Reset the render target
	SDL_SetRenderTarget(pRenderer, NULL);

	// Render the target texture
	if(pTargetTexture)
		SDL_RenderCopy(pRenderer, pTargetTexture, NULL, NULL);

	// Update the screen
	SDL_RenderPresent(pRenderer);
}

// Destroy the target texture
if(pTargetTexture)
	SDL_DestroyTexture(pTargetTexture);

// Destroy the image texture
if(pTexture)
	SDL_DestroyTexture(pTexture);

// Destroy the renderer
SDL_DestroyRenderer(pRenderer);
pRenderer = NULL;

// Destroy the window
SDL_DestroyWindow(pWindow);
pWindow = NULL;

// Quit SDL
SDL_Quit();

return 0;

}

I’ve made a code example showing how to render a image texture (‘pTexture’) onto another texture (‘pTargetTexture’). Code below.

Code:

#include “SDL.h”

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

SDL_Window* pWindow = NULL;
SDL_Renderer* pRenderer = NULL;

SDL_Texture* pTexture = NULL;
SDL_Texture* pTargetTexture = NULL;

SDL_Event Event;

bool Running = true;

int main(int argc, char* argv[])
{
// Initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
// If there was a problem initializing SDL
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, “Couldn’t initialize SDL: %s\n”, SDL_GetError());
}

// If SDL was successfully initialized
else
{
	// Create the window
	pWindow = SDL_CreateWindow("Render To Texture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);

	if(pWindow)
	{
		// Create the renderer with the render to texture option enabled
		pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

		if(pRenderer)
		{
			// Set the render draw color
			SDL_SetRenderDrawColor(pRenderer, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);


			SDL_Surface* pSurface = NULL;
			pSurface = SDL_LoadBMP("Image.bmp");

			if(pSurface)
			{
				// Create the image texture
				pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
			
				// Destroy the temporary surface
				SDL_FreeSurface(pSurface);
			}


			// Create the target texture with the render target option enabled
			pTargetTexture = SDL_CreateTexture(pRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, WINDOW_WIDTH, WINDOW_HEIGHT);
		}
	}
}

while(Running)
{
	while(SDL_PollEvent(&Event))
	{
		if(Event.type == SDL_QUIT)
		{
			Running = false;
			break;
		}
	}

	// Clear the current render target
	SDL_RenderClear(pRenderer);


	// Set the target texture as the current render target
	if(pTargetTexture)
		SDL_SetRenderTarget(pRenderer, pTargetTexture);
	

	if(pTexture)
	{
		SDL_Rect TextureQuad = {0, 0, 0, 0};
		
		SDL_QueryTexture(pTexture, NULL, NULL, &TextureQuad.w, &TextureQuad.h);

		TextureQuad.x = (WINDOW_WIDTH - TextureQuad.w) / 2;
		TextureQuad.y = (WINDOW_HEIGHT - TextureQuad.h) / 2;

		// Render the image texture in the middle of the window (onto the target texture)
		SDL_RenderCopy(pRenderer, pTexture, NULL, &TextureQuad);
	}


	// Reset the render target
	SDL_SetRenderTarget(pRenderer, NULL);


	// Render the target texture
	if(pTargetTexture)
		SDL_RenderCopy(pRenderer, pTargetTexture, NULL, NULL);


	// Update the screen
	SDL_RenderPresent(pRenderer);
}

// Destroy the target texture
if(pTargetTexture)
	SDL_DestroyTexture(pTargetTexture);

// Destroy the image texture
if(pTexture)
	SDL_DestroyTexture(pTexture);

// Destroy the renderer
if(pRenderer)
{
	SDL_DestroyRenderer(pRenderer);
	pRenderer = NULL;
}

if(pWindow)
{
	// Destroy the window
	SDL_DestroyWindow(pWindow);
	pWindow = NULL;
}

// Quit SDL
SDL_Quit();

return 0;

}

https://wiki.libsdl.org/SDL_SetRenderTarget

Pallav Nawani
IronCode Gaming Private Limited
Website: http://www.ironcode.com
Twitter: http://twitter.com/Ironcode_Gaming
Facebook: http://www.facebook.com/Ironcode.Gaming
Mobile: 9997478768On Fri, Sep 12, 2014 at 2:04 AM, Midi wrote:

Before anyone asks, yes, I have checked Google.

I’ve been searching for a way to render a texture onto another texture. My
problem is I need to be able to draw things to particular layers, and
textures seem to only be able to draw directly to the screen or to a
viewport. Whenever I look online, I just find links that lead back to the
wiki page on rendering a texture to the screen. Is it possible to render a
texture onto another texture without having to use surfaces and then
converting to textures (which kinda defeats the point of textures in the
first place, but I’ve actually had people tell me to do that).


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org