c++sdlsdl-2render-to-texture

SDL2 not copying textures to renderer


I've been using SDL2 to make a simple game for a few months. I recently tried to add lighting, but when I try and render the lights or any other layers, the screen is just black.

I've tried the same code on a different testing project, and it worked. I can't render png's either anymore, except sometimes I can. I have no idea what's causing the problem.

This is how my surfaces are initialized in both my main code and my testing code (just simple SDL_Texture*'s)

this->background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, this->dimensions.w, this->dimensions.h);

this->lightLayer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, this->dimensions.w, this->dimensions.h);
SDL_SetTextureBlendMode(lightLayer, SDL_BLENDMODE_MOD);

this->resultLayer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, this->dimensions.w, this->dimensions.h);
SDL_SetTextureBlendMode(resultLayer, SDL_BLENDMODE_BLEND);

SDL_SetRenderDrawColor(this->renderer, 0x00, 0x00, 0x00, 0xff);

My render function (this is where the problem is)

// Not using lightLayer until I get the background working
SDL_SetRenderTarget(this->renderer, this->resultLayer);
SDL_RenderClear(this->renderer);

SDL_RenderCopy(this->renderer, this->background, NULL, &this->dimensions);
// SDL_RenderCopy(this->renderer, this->lightLayer, NULL, &this->dimensions);

SDL_SetRenderTarget(this->renderer, NULL);
SDL_RenderCopy(this->renderer, this->resultLayer, NULL, &this->dimensions);
SDL_RenderPresent(this->renderer);

SDL_RenderClear(this->renderer);

SDL_SetRenderTarget(this->renderer, this->background);
SDL_RenderClear(this->renderer);

// SDL_SetRenderTarget(this->renderer, this->lightLayer);
// SDL_RenderClear(this->renderer);

Where my background is rendered. This works fine if I set the render target to NULL (The render window), but if I render to background the screen just appears black, because background isn't being rendered.

void Game::renderSprite(Entity& entity, SDL_Texture* renderSurface)
{
    SDL_SetRenderTarget(this->renderer, this->background); // If I set the second argument to null, it works fine

    //std::cout << "Rendered " << entity.type() << " at " << entity.getCoords().x << ", " << entity.getCoords().y << "\n";
    SDL_Rect src;
    src.x = entity.getSpriteSheetRect().x;
    src.y = entity.getSpriteSheetRect().y;
    src.w = entity.getSpriteSheetRect().w;
    src.h = entity.getSpriteSheetRect().h;

    SDL_Rect dest;
    dest.x = entity.getDimensions().x;
    dest.y = entity.getDimensions().y;
    dest.w = entity.getDimensions().w;
    dest.h = entity.getDimensions().h;

    SDL_RenderCopy(this->renderer, entity.getTexture(), &src, &dest);
}

And this is my main loop that calls the functions

// Renders all the tiles to the screen
for (Chunk& chunk : *renderVec)
{
    for (Tile& tile : chunk.getTiles())
    {
        game.renderSprite(tile, game.background);
    }
}

...

game.present();

This is my testing code that works fine. There are some inconsistencies between the testing code, and my actual code, but that's because of debugging. I have copy-pasted the testing code in and it still doesn't work.

SDL_Texture* bgTexture = loadTexture(renderer, "game.png");

// light spot
SDL_Texture* light = loadTexture(renderer, "spot.png");
// layers
SDL_Texture* background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 640, 480);
SDL_Texture* lightLayer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 640, 480);
SDL_SetTextureBlendMode(lightLayer, SDL_BLENDMODE_MOD);
SDL_Texture* resultLayer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 640, 480);
SDL_SetTextureBlendMode(resultLayer, SDL_BLENDMODE_BLEND);

SDL_Rect spot1 = { 10, 10, 200, 200 };

while (quit != 1)
{
    // Rendering sprites
    // Background
    SDL_SetRenderTarget(renderer, background);
    SDL_RenderCopy(renderer, bgTexture, NULL, NULL);

    // Lights
    SDL_SetRenderTarget(renderer, lightLayer);
    SDL_Rect spot = { 640, 360, 300, 300 };
    SDL_RenderCopy(renderer, light, NULL, &spot); // Middle-ish



    // Rendering everything
    SDL_SetRenderTarget(renderer, resultLayer);
    // Background
    SDL_RenderCopy(renderer, background, NULL, &dimensions);
    // Lights
    SDL_RenderCopy(renderer, lightLayer, NULL, &dimensions);

    // Putting everything on the screen
    SDL_SetRenderTarget(renderer, NULL);
    SDL_RenderCopy(renderer, resultLayer, NULL, &dimensions);

    // Presenting
    SDL_RenderPresent(renderer);



    // Clearing render targets; which also draws the desired color
    // Window
    SDL_RenderClear(renderer);

    // Background
    SDL_SetRenderTarget(renderer, background);
    SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xff);
    SDL_RenderClear(renderer);

    // Shadow/light layer        Set to SDL_BLENDMODE_MOD
    SDL_SetRenderTarget(renderer, lightLayer);
    SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xff); // Alpha value doesn't matter
    // any color besides black is some degree of transparent. Eg. Blue is seen below
    //SDL_SetRenderDrawColor(renderer, 50, 69, 155, 255); // More transparent color
    // Fill screen with color; Doesn't matter which one
    //SDL_RenderFillRect(renderer, NULL);
    SDL_RenderClear(renderer); // Prefered: Can clear the surface and set color, and is platform independant

    // Result layer              Set to SDL_BLENDMODE_BLEND
    SDL_SetRenderTarget(renderer, resultLayer);
    SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xff);
    SDL_RenderClear(renderer);

I'm using visual studio 2022 with MSVC compiler, and C++20.


Solution

  • I replaced &this->dimensions with NULL, because when I created the game object, the x and y values were assigned to the very big number SDL_WINDOWPOS_CENTERED, (which is 0x2FFF0000 in hex or 805240832 in decimal), so it was rendering the texture off screen.