我已经使用 SDL2 制作一个简单的游戏几个月了。我最近尝试添加照明,但是当我尝试渲染灯光或任何其他图层时,屏幕只是黑色。
我在不同的
testing
项目上尝试了相同的代码,并且它有效。我也无法再渲染 png,除非有时可以。我不知道是什么导致了这个问题。
这就是我的表面在我的主代码和
testing
代码中初始化的方式(只是简单的SDL_Texture *)
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);
我的渲染函数(这就是问题所在)
// 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_RenderPresent(this->renderer);
SDL_SetRenderTarget(this->renderer, this->background);
SDL_RenderClear(this->renderer);
// SDL_SetRenderTarget(this->renderer, this->lightLayer);
// SDL_RenderClear(this->renderer);
我的背景被渲染的地方。如果我将渲染目标设置为
NULL
(渲染窗口),则效果很好,但如果我渲染到 background
,则屏幕只会显示为黑色,因为 background
没有被渲染。
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);
}
这是我调用函数的主循环
// Renders all the tiles to the screen
for (Chunk& chunk : *renderVec)
{
for (Tile& tile : chunk.getTiles())
{
game.renderSprite(tile, game.background);
}
}
...
game.present();
这是我的测试代码,运行良好。测试代码和我的实际代码之间存在一些不一致,但这是因为调试的原因。我把测试代码复制粘贴进去了,还是不行。
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);
我正在使用带有 MSVC 编译器的 Visual Studio 2022,并且
C++20
。
这是我的第一篇文章,所以我可能错过了一些东西。
我建议您阅读 SDL_SetRenderTarget() 文档,还有这个答案:https://stackoverflow.com/a/21007477/8204677 这可能会清除您遇到的问题。
你的渲染函数
// 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_RenderPresent(this->renderer);
SDL_SetRenderTarget(this->renderer, this->background);
SDL_RenderClear(this->renderer);
// SDL_SetRenderTarget(this->renderer, this->lightLayer);
// SDL_RenderClear(this->renderer);
我的背景被渲染的地方。如果我设置渲染,效果很好 目标为 NULL (渲染窗口),但如果我渲染到背景 屏幕只是显示为黑色,因为背景未渲染。
要回答这个具体问题,我相信你需要了解渲染的工作原理。在您的渲染函数中,您声称您正在尝试渲染背景,但它不起作用。我想您正在谈论使用
SDL_RenderPresent(this->renderer);
复制背景后的 SDL_RenderCopy()
。由于您之前使用 this->resultlayer
将渲染目标设置为 SDL_SetRenderTarget()
,因此您不再渲染到窗口。要根据文档执行此操作,您需要:
停止渲染到纹理并渲染到窗口 再次使用 NULL 纹理调用此函数。
我相信你自己也提到过。与您在“测试代码”中所做的类似,如果您希望将结果层呈现到窗口中,您可以对结果层执行此操作:
// Putting everything on the screen
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, resultLayer, NULL, &dimensions);
我想总结/TLDR是:您正在渲染纹理而不是窗口,这就是您遇到黑屏的原因。