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
.
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.