我用C&SDL2编写了一个程序:
-
创建一个窗口
-
获取窗口的表面
-
为窗口创建渲染器
-
将一些填充的矩形渲染到窗口上
-
从窗口的表面创建纹理
-
清除屏幕
-
将一些实心圆圈渲染到窗口上
-
从窗口的表面创建第二个纹理
-
进入事件循环,每次按下一个键:
-
如果当前正在显示圆圈,则使用SDL_RenderCopy()将方块纹理复制到窗口 .
-
否则如果当前正在显示方块,则将圆形纹理复制到窗口 .
如果使用SDL_RENDERER_SOFTWARE标志创建渲染器,则该程序可以正常工作 .
如果使用SDL_RENDERER_ACCELERATED标志创建渲染器,我发现虽然我可以直接渲染到屏幕,但是如果我从窗口的表面创建了几个不同的纹理,然后尝试使用SDL_RenderCopy()将它们复制回窗口;我只看到一个黑色的窗户 .
我找不到任何失败的SDL呼叫 .
我想知道纹理格式和渲染器之间是否存在某些不兼容性 - 但我不确定如何跟进它 .
任何帮助或建议?
我的环境是:
-
Windows 10
-
Visual Studio社区2015
-
SDL2版本2.0.4
其他信息和源代码:
我添加了减少的源代码来演示下面的问题 .
请注意,为了减小大小,我删除了所有错误检查并将相关代码合并到一个主函数中 .
我得到的是,如果我取消对第40行的注释,以便我使用SDL_RENDERER_SOFTWARE标志调用SDL_CreateRenderer,该程序将按预期为我工作 .
如果我取消注释任何其他SDL_CreateRenderer行(第41-43行:使用硬件加速),我会在最初渲染到屏幕时看到红色和蓝色方块 .
但是当我按下按键时,而不是在红色和蓝色方块之间轻弹的窗口,我正在看一个黑色的窗口 .
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main(int argc, char* args[])
{
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;
//And two textures, one for a red square, on for a blue square
SDL_Texture* texture_red = NULL;
SDL_Texture* texture_blue = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Initialize SDL
SDL_Init(SDL_INIT_VIDEO);
//Create window
gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
//Get the screen surface
gScreenSurface = SDL_GetWindowSurface(gWindow);
//Create renderer for window
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_SOFTWARE);
//gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
//gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_PRESENTVSYNC);
//gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
/*###########################################################################################
# I can not figure out how to make this program work with hardware acceleration. It works #
# fine when I define the renderer using SDL_RENDERER_SOFTWARE, but doesn't display anything #
# if I define the renerer using the SDL_RENDERER_ACCELERATED flag #
###########################################################################################*/
//Initialize renderer color
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
//Clear screen
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(gRenderer);
//Render red filled quad
SDL_Rect fillRect = { 100, 75, 100, 100 };
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0x00, 0x00, 0xFF);
SDL_RenderFillRect(gRenderer, &fillRect);
//Update the rendered image on screen
SDL_RenderPresent(gRenderer);
//Pause long enough to see it
SDL_Delay(200);
//Create texture_red texture from the screen surface
texture_red = SDL_CreateTextureFromSurface(gRenderer, gScreenSurface);
//Clear screen
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(gRenderer);
//Render blue filled quad
fillRect = { 225, 250, 100, 100 };
SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0xFF, 0xFF);
SDL_RenderFillRect(gRenderer, &fillRect);
//Update the rendered image on screen
SDL_RenderPresent(gRenderer);
//Pause long enough to see it
SDL_Delay(200);
//Create texture_red texture from the screen surface
texture_blue = SDL_CreateTextureFromSurface(gRenderer, gScreenSurface);
//Main loop flag
bool quit = false;
//Flag to keep track of which colour we're currently looking at
bool blue = true;
//Event handler
SDL_Event e;
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
//User presses a key
else if (e.type == SDL_KEYDOWN)
{
//Select surfaces based on key press
switch (e.key.keysym.sym)
{
case SDLK_ESCAPE:
quit = true;
break;
default:
if (blue)
{
//Copy surface used to store red image onto the screen surface
SDL_RenderCopy(gRenderer, texture_red, NULL, NULL);
//Update current colour flag
blue = false;
}
else
{
//Copy surface used to store blue image onto the screen surface
SDL_RenderCopy(gRenderer, texture_blue, NULL, NULL);
//Update current colour flag
blue = true;
}
//Update the screen with recent render activity
SDL_RenderPresent(gRenderer);
break;
}
}
}
}
//Deallocate surfaces
SDL_FreeSurface(gScreenSurface);
//Destroy window
SDL_DestroyWindow(gWindow);
gWindow = NULL;
//Quit SDL subsystems
SDL_Quit();
return 0;
}
2 回答
SDL_GetWindowSurface()
header comment明确禁止将其与SDL_Renderer功能一起使用:如果要捕获SDL_Renderer输出,请使用
SDL_RENDERER_TARGETTEXTURE
&SDL_SetRenderTarget() .您可以使用SDL_GetRendererInfo()查询兼容的纹理格式 . 或者只是向前推进
SDL_PIXELFORMAT_ARGB8888
like testrendertarget.c does并希望最好的:)尝试将SDL_RENDERER_PRESENTVSYNC添加到渲染器的标记中(由SDL2 strange behaviour of hardware rendering中的某人建议) .
C似乎是您正在使用的编程语言,但对于那些寻找完全工作的基于SDL2.0.8的C程序而不使用GetWindowSurface()的人,请查看:
https://github.com/BoubacarDiene/mmstreamer/blob/master/src/graphics/drawers/Drawer2.c
主要是, - initWindowAndRenderer - drawText - drawImage - drawVideo - setBgColor - drawVideo - ...