如果我使用opengl绘图,SDL渲染器是否无用?

时间:2016-12-11 22:31:24

标签: c++ opengl sdl-2 opengl-3

我正在学习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要求渲染。

2 个答案:

答案 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的教程,legacymodern。请注意,这两者都不涉及创建SDL渲染器。 事实上,使用它是不合适的,因为这两个API是互斥的:你应该使用其中一个。 This answer快速解释了为什么不应该混用它们。

然而,有一些方法可以使用OpenGL从某些SDLRenderer调用获得相同的输出(因为相同的渲染器具有OpenGL实现!),但这自然会特定于案例。想画一个简单的矩形?遗留glBeginglEnd方法可能就足够了。想画一个精灵?您必须先将其发送到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
}
}