Draw sprites off screen

I want to know a good way to draw sprites off screen on a surface or something then onto the screen.

I only want the text to redraw (each unique character is a separate graphic) when there’s any changes.

I’ve been trying with SDL_Surface, but I’m not sure that’s the best way.

If you want to render to an off-screen buffer, and don’t want to use the default render target (buffer), you can always render to a render target texture. Then, when the render to it is finished, you render that specific texture to the default render target, effectively render the texture to a specific position in the window.

Can you give me (or direct me to) a code example?

A code example has been added below.

Basically what the code does is:

  1. Initialize SDL
  2. Create the SDL window
  3. Create the SDL renderer, with render-to-texture functionality enabled
  4. Create an empty SDL texture, which will be used as a render target
  5. In the render loop, set the render target texture as the current render target
  6. Clear it to some color (optionally)
  7. Render whatever object(s) that should be rendered
  8. Reset the render target back to the default render target
  9. Render the actual render target texture to the default render target (i.e the window/screen)
  10. Repeat process 5-9 every frame

Note that I haven’t done any error checking whatsoever in the code, to reduce code length, and normally this should always be made.

Code example
#include <SDL.h>

#define WINDOW_WIDTH			(800)
#define WINDOW_HEIGHT			(600)
#define RENDER_TARGET_WIDTH		(320)
#define RENDER_TARGET_HEIGHT	(240)

SDL_Window*		pWindow		= nullptr;
SDL_Renderer*	pRenderer	= nullptr;

SDL_Texture* pRenderTarget = nullptr;

SDL_Event Event;

bool Running = true;

void Update (void);
void Render (void);

int main(int argc, char *argv[])
{
	SDL_Init(SDL_INIT_EVERYTHING);

	pWindow = SDL_CreateWindow("SDL - render to texture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);

	// Note the SDL_RENDERER_TARGETTEXTURE flag, which enables render-to-texture functionality
	pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

	/*
	Create a blank texture which will be used as a render target
	Note the SDL_TEXTUREACCESS_TARGET flag, which means the texture can be used as a render target
	*/
	pRenderTarget = SDL_CreateTexture(pRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT);

	// Set the texture as the current render target and clear the whole render target texture to black
	SDL_SetRenderTarget(pRenderer, pRenderTarget);
	SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 255);
	SDL_RenderClear(pRenderer);

	// And reset back to the default render target (i.e, the window/screen)
	SDL_SetRenderTarget(pRenderer, nullptr);

	while(Running)
	{
		Update();
		Render();
	}

	SDL_DestroyTexture(pRenderTarget);
	SDL_DestroyRenderer(pRenderer);
	SDL_DestroyWindow(pWindow);
	SDL_Quit();

	return 0;
}

void Update(void)
{
	HandleSDLEvents();
}

void Render(void)
{
	// Set the render target texture as the current render target
	SDL_SetRenderTarget(pRenderer, pRenderTarget);

	/*
	Note: everything from now on will be rendered to the render target texture,
	until the render target are reset back to the default render target
	*/

	// Clear the render target texture to black
	SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 255);
	SDL_RenderClear(pRenderer);

	// Render a red quad/square to the render target texture
	SDL_SetRenderDrawColor(pRenderer, 255, 0, 0, 255);
	const SDL_Rect Quad = {20, 20, 60, 60};
	SDL_RenderFillRect(pRenderer, &Quad);

	// Render a diagonal yellow line to the render target texture
	SDL_SetRenderDrawColor(pRenderer, 255, 255, 0, 255);
	SDL_RenderDrawLine(pRenderer, 20, 100, 180, 180);

	// Reset the render target back to the default render target
	SDL_SetRenderTarget(pRenderer, nullptr);

	//////////////////////////////////////////////////////////////////////////

	// Clear the default render target to white
	SDL_SetRenderDrawColor(pRenderer, 255, 255, 255, 255);
	SDL_RenderClear(pRenderer);

	const SDL_Rect SrcQuad = { 0,  0, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT};
	const SDL_Rect DstQuad = {50, 50, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT};

	// Render the actual render target texture to the default render target
	SDL_RenderCopy(pRenderer, pRenderTarget, &SrcQuad, &DstQuad);

	// And update the window/screen
	SDL_RenderPresent(pRenderer);
}

Thanks Naith, I’ll post how I go later.

Got it working, and this is with the D programming language (with minor changes, and a small wrapper of mine and using a binding) too. Thanks Naith.

I can’t get it working in my non testing code. It does the whole window when It’s supposed to just be part, and no textures show (a line does though). Is there a gotcha here?

[edit]

It’s behaving correctly now. I was using a struct, and it was de-allocating all the time, but not with class. I want to be using struct though.

Glad to hear that it finally works. :slight_smile: