如果我使用OpenGL进行绘制,SDL渲染器是否毫无用处?

mbjcgjjk  于 2022-09-26  发布在  其他
关注(0)|答案(4)|浏览(202)

我正在学习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()从精灵工作表绘制图像:

//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,因为它似乎与我正在使用的gui库不兼容,我不明白如何使用sdl2来绘制东西(就像在Sprite示例中一样),该库使用OpenGL调用进行渲染。

dohp0rv5

dohp0rv51#

我现在可以不使用任何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的调用。问题中链接的同一网站提供了在SDL2(legacymodern)中使用OpenGL的教程。请注意,这两种方法都不涉及创建SDL渲染器。事实上,使用它是不合适的,因为这两个API是相互排斥的:您应该使用其中一个。This answer快速解释了为什么不应该混合它们。

尽管如此,还是有一些方法可以使用OpenGL从特定的SDLReneller调用中获得相同的输出(因为同一个渲染器有一个OpenGL实现!),但这自然会根据具体情况而定。想要画一个简单的矩形吗?传统的glBeginglEnd方法可能就足够了。想画个精灵吗?您必须首先将其发送到OpenGL设备的内存中。一旦您了解了OpenGL的诀窍,制作一个合适的 Package 层通常是合适的。如果您想要使用依赖于OpenGL的现有库,则替换其他绘制过程以使用此API(或GLU等实用程序库)是正确的方法。

另请注意,SDL渲染器不必依赖OpenGL(它可以在Windows上使用Direct3D)。

drkbr07n

drkbr07n2#

如果我理解为您想知道如何在不使用SDL函数的情况下渲染到SDL屏幕,那么您应该使用OpenGL函数。SDL支持OpenGL,要使用SDL使用OpenGL渲染事物,您必须遵循以下最起码的步骤:在创建窗口之前,调用SDL_GL_SetAttribute以设置OpenGL属性,然后使用SDL_WINDOW_OPENGL标志创建窗口,之后必须创建调用SDL_GL_CreateContext的OpenGL上下文(每个GL应用程序都有一个),请参阅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
}
}
brqmpdu1

brqmpdu13#

自2021年10月12日起,您需要版本>=1.85和SDL版本>=2.0.18+

如果要学习基于SDL_Renderer的教程,请使用该选项。

另外,作为技术问题,如果您使用OpenGL后端,您仍然可以使用SDL_Render渲染到屏幕外渲染目标,然后将其作为OpenGL纹理上载到OpenGL。亲爱的ImGui正是通过执行这个“一般”过程来提供多个后端的。

或者,您也可以直接写入OpenGL帧缓冲区(不需要纹理)。对于初学者教程,只需将>v1.85与SDL_Renisher一起使用。

0vvn1miw

0vvn1miw4#

由于您使用的是ImGui,因此不需要为2D游戏使用SDL渲染器或OpenGL绘制函数。ImGui为您提供了一些功能。这就是你使用ImGui的原因,对吗?制作一个全屏窗口,获取其绘图列表,并使用AddImage()等函数绘制图像。有关类似的其他函数,请参见imgui.h。

// Create a full screen window  
ImGuiIO& io = ImGui::GetIO();
const ImGuiWindowFlags mainFlags = ImGuiWindowFlags_NoResize
        | ImGuiWindowFlags_NoCollapse
        | ImGuiWindowFlags_NoTitleBar
        | ImGuiWindowFlags_NoScrollbar
        | ImGuiWindowFlags_NoBackground
        | ImGuiWindowFlags_NoMove
        | ImGuiWindowFlags_NoSavedSettings
        | ImGuiWindowFlags_NoBringToFrontOnFocus;

ImGui::SetNextWindowPos(ImVec2(0.0, 0.0));
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y));
ImGui::Begin("Game scene", NULL, mainFlags);

// Get draw list
ImDrawList* draw_list = ImGui::GetWindowDrawList();

// Get viewport
ImVec2 canvasViewportStart = ImGui::GetCursorScreenPos();

// Load texture (to be implemented by you)
auto texture = loadTexture("texture.png");

// Draw the texture
draw_list->AddImage(texture, ImVec2(canvasViewportStart.x, canvasViewportStart.y), ImVec2(canvasViewportStart.x + 32, canvasViewportStart.y + 32));

// Handle mouse input
if (ImGui::IsWindowHovered()) {
    const ImVec2 mousePosAbs = ImGui::GetMousePos();
    const ImVec2 mousePos = ImVec2(mousePosAbs.x - canvasViewportStart.x, mousePosAbs.y - canvasViewportStart.y);

    if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
        // ...
    }
}                   

ImGui::End();

// Create other windows, call ImGui::Render()

如果你想直接使用OpenGL绘图功能(可能是3D游戏),这也是可能的。在这种情况下,不应为场景创建ImGui窗口。在渲染ImGui窗口之前渲染场景。将代码放在ImGui OpenGL示例中的渲染调用之间:

ImGui::Render();

// Clear the screen
ImGuiIO& io = ImGui::GetIO();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(0, 0, 0, 255);
glClear(GL_COLOR_BUFFER_BIT);

// Render your own game scene here
// Note: You don't need this if you are using ImGui draw functions

// Render ImGui windows
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window);

相关问题