我正在学习SDL2,但我也在使用正在使用OpenGL调用的imgui库。从我在网上各种博客上看到的内容来看,我无法轻松混合SDL2渲染器和opengl调用;我要么使用其中一种。
我读过的大部分教程都使用了渲染器,所以我不太清楚如何在没有渲染器的情况下使用SDL2来绘制图元或绘制精灵。
以此为例:http://lazyfoo.net/tutorials/SDL/11_clip_rendering_and_sprite_sheets/index.php
他创建了sdl渲染器:
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
然后他用它来渲染图像:
void LTexture::render( int x, int y, SDL_Rect* clip )
{
//Set rendering space and render to screen
SDL_Rect renderQuad = { x, y, mWidth, mHeight };
//Set clip rendering dimensions
if( clip != NULL )
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
//Render to screen
SDL_RenderCopy( gRenderer, mTexture, clip, &renderQuad );
}
然后他调用他的render()
从spritesheet中绘制图像:
//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );
//Render top left sprite
gSpriteSheetTexture.render( 0, 0, &gSpriteClips[ 0 ] );
//Render top right sprite
gSpriteSheetTexture.render( SCREEN_WIDTH - gSpriteClips[ 1 ].w, 0, &gSpriteClips[ 1 ] );
//Render bottom left sprite
gSpriteSheetTexture.render( 0, SCREEN_HEIGHT - gSpriteClips[ 2 ].h, &gSpriteClips[ 2 ] );
//Render bottom right sprite
gSpriteSheetTexture.render( SCREEN_WIDTH - gSpriteClips[ 3 ].w, SCREEN_HEIGHT - gSpriteClips[ 3 ].h, &gSpriteClips[ 3 ] );
//Update screen
SDL_RenderPresent( gRenderer );
我理解发生了什么,但现在我无法使用sdl渲染器,我该如何做到这一点?我现在不能使用任何SDL2绘图功能吗?我只使用原始的opengl调用,并且只使用SDL进行键盘绑定吗?
基本上,如果我不能使用SDL Renderer
,我不明白如何使用SDL2来绘制内容(例如在精灵示例中),因为它似乎与我使用的gui库不兼容,后者使用opengl要求渲染。
答案 0 :(得分:5)
我现在不能使用任何SDL2绘图功能吗?我只使用原始的opengl调用,并且只使用SDL进行键盘绑定吗?
正确。
为了直接使用OpenGL API,必须使用标志SDL_WINDOW_OPENGL
创建SDL窗口,并为其创建新的OpenGL上下文:
auto window = SDL_CreateWindow("Window name",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN);
auto context = SDL_GL_CreateContext(window);
如果成功,可以像在任何其他上下文处理程序中一样执行对OpenGL的调用。该问题中链接的同一网站提供了使用OpenGL和SDL 2的教程,legacy和modern。请注意,这两者都不涉及创建SDL渲染器。 事实上,使用它是不合适的,因为这两个API是互斥的:你应该使用其中一个。 This answer快速解释了为什么不应该混用它们。
然而,有一些方法可以使用OpenGL从某些SDLRenderer调用获得相同的输出(因为相同的渲染器具有OpenGL实现!),但这自然会特定于案例。想画一个简单的矩形?遗留glBegin
和glEnd
方法可能就足够了。想画一个精灵?您必须先将其发送到OpenGL设备的内存。一旦了解了OpenGL周围的绳索,制作合适的包装层通常是合适的。
如果您想使用依赖OpenGL的现有库,则替换其他绘图过程以使用此API(或GLU等实用程序库)是正确的方法。
另请注意,SDL渲染器不必依赖OpenGL(它可能在Windows上使用Direct3D)。
答案 1 :(得分:0)
如果我已经了解您想要知道如何在不使用SDL功能的情况下渲染到SDL屏幕,则需要使用opengl函数。 SDL支持opengl,使用SDL使用opengl渲染事物必须遵循以下最小步骤:在创建窗口之前,先调用SDL_GL_SetAttribute
来设置OpenGL属性,然后创建带有SDL_WINDOW_OPENGL
标志的窗口之后你必须创建opengl上下文(每个gl applciation有一个)调用SDL_GL_CreateContext
,请参阅SDL Wiki了解我提到的函数:CategoryVideo - SDL Wiki
以下是一段代码示例:
void start(SDL_Window** window, SDL_GLContext* gl){
if(SDL_Init(SDL_INIT_VIDEO) < 0){
throw std::runtime_error(SDL_GetError());
}
//set the gl version to be loaded
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
*window = SDL_CreateWindow("Widget Tests", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL);
if(*window == nullptr){
throw std::runtime_error(SDL_GetError());
}
//create the opengl context
*gl = SDL_GL_CreateContext(*window);
if(*gl == nullptr){
throw std::runtime_error(SDL_GetError());
}
}
int main(){
SDL_Window* window;
SDL_GLContext gl;
...
//init sdl and opengl
start(&window, &gl);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW_MATRIX);
glLoadIdentity();
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
while(running){
while(SDL_PollEvent(&event)){
switch(event.type){
...
}
}
glClear(GL_COLOR_BUFFER_BIT);
//... draw calls with opengl
SDL_GL_SwapWindow(window);//update the window
}
}