使用SDL2渲染器绘制填充四边形/三角形的最快方式是什么?

14

我有一个使用SDL2编写的游戏,并使用SDL2渲染器(硬件加速)进行绘制。有没有什么技巧可以画填充的四边形或三角形?

目前我只是通过绘制很多线段(SDL_Drawlines)来填充它们,但性能很差。

我不想使用OpenGL。


嗯,第一个使用OpenGL,第二个只是矩形 :) - Tom Davies
不确定你是否能找到一个合理的OpenGL替代方案(不包括专有/操作系统特定的兄弟Direct3d和Metal)。我曾经在Qt / QPainter中绘制了一个HUD(我的渲染3D内容的注释),希望Qt在幕后也使用OpenGL。但是,由于性能差的投诉,我将代码移植到“手写”的OpenGL上,并且任务成功完成。当然,可能还有其他API可以做得更好... - Scheff's Cat
3个回答

17

SDL_RenderGeometry()/SDL_RenderGeometryRaw()是在SDL 2.0.18中添加的:

  • 添加了SDL_RenderGeometry()SDL_RenderGeometryRaw(),允许使用SDL 2D渲染API来渲染任意形状

示例:

screenshot

// g++ main.cpp `pkg-config --cflags --libs sdl2`
#include <SDL.h>
#include <vector>

int main( int argc, char** argv )
{
    SDL_Init( SDL_INIT_EVERYTHING );
    SDL_Window* window = SDL_CreateWindow("SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN );
    SDL_Renderer* renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );

    const std::vector< SDL_Vertex > verts =
    {
        { SDL_FPoint{ 400, 150 }, SDL_Color{ 255, 0, 0, 255 }, SDL_FPoint{ 0 }, },
        { SDL_FPoint{ 200, 450 }, SDL_Color{ 0, 0, 255, 255 }, SDL_FPoint{ 0 }, },
        { SDL_FPoint{ 600, 450 }, SDL_Color{ 0, 255, 0, 255 }, SDL_FPoint{ 0 }, },
    };

    bool running = true;
    while( running )
    {
        SDL_Event ev;
        while( SDL_PollEvent( &ev ) )
        {
            if( ( SDL_QUIT == ev.type ) ||
                ( SDL_KEYDOWN == ev.type && SDL_SCANCODE_ESCAPE == ev.key.keysym.scancode ) )
            {
                running = false;
                break;
            }
        }

        SDL_SetRenderDrawColor( renderer, 0, 0, 0, SDL_ALPHA_OPAQUE );
        SDL_RenderClear( renderer );
        SDL_RenderGeometry( renderer, nullptr, verts.data(), verts.size(), nullptr, 0 );
        SDL_RenderPresent( renderer );
    }

    SDL_DestroyRenderer( renderer );
    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}

请注意,由于API缺少仅针对Z坐标的数据通道,因此只有仿射纹理映射可以实现。


2
哇,错过了这个。对于SDL2渲染器来说是一个重大的改变 :) - Tom Davies
@TomDavies:是的,只是一点点 :) - genpfault
1
应该为像nuklear这样的立即模式GUI制作基于SDL_Renderer的后端,也是可行的。 - genpfault
1
感谢让我知道nuklear。在我的游戏中,我使用dear-imgui(与一个中间库一起使用SDL2渲染器呈现imgui-速度有点慢),但是这个看起来也非常不错。 - Tom Davies
关于SDL_Renderer后端的翻译:https://github.com/Immediate-Mode-UI/Nuklear/pull/280 - genpfault
1
作为跟进,我刚刚构建了最新的SDL源代码,并第一次绘制了填充三角形。真是令人兴奋的日子,谢谢。如果不是我只检查官方发布版本,我可能不会注意到这一点。 - Tom Davies

0

不可能。SDL2不包括一个完整的渲染引擎。

一些选项:

  • 您可以采用Skia(Chrome等中使用的图形库),然后要么坚持使用软件渲染器,要么实例化一个OpenGL上下文并使用硬件后端。

  • 您可以使用另一个2D绘图库,例如Raylib

  • 或者只是咬紧牙关,使用OpenGL绘制三角形。


0

这是我的基本示例:

#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>

int width=1280,height=720;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Event e;

SDL_Vertex triangleVertex[3]=
{
 {
  { 0,0}, /* first point location */ 
  { 255, 0, 0, 0xFF }, /* first color */ 
  { 0.f, 0.f }
 },
 {
  { 0, 720 }, /* second point location */ 
  { 0,255,0, 0xFF }, /* second color */
  { 0.f, 0.f }
 },
 {
  { 640, 360 }, /* third point location */ 
  { 0,0,255, 0xFF }, /* third color */
  { 0.f, 0.f }
 }
};


int main(int argc, char** argv)
{
 if(SDL_Init(SDL_INIT_VIDEO)){printf( "SDL could not initialize! SDL_Error: %s\n",SDL_GetError());return -1;}

 window = SDL_CreateWindow( "SDL Chaste Triangle",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,width,height,0);
 if(window==NULL){printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );return -1;}

 renderer = SDL_CreateRenderer(window,-1,0);
 if(renderer==NULL){printf( "Renderer could not be created! SDL_Error: %s\n", SDL_GetError() );return -1;}
    
 SDL_SetRenderDrawColor(renderer,0,0,0,255);
 SDL_RenderClear(renderer);
 if( SDL_RenderGeometry(renderer, NULL, triangleVertex, 3, NULL, 0) < 0 ) {SDL_Log("%s\n", SDL_GetError());}

 SDL_RenderPresent(renderer);
    
 while(e.type != SDL_KEYUP && e.type != SDL_QUIT) /*wait until any key is pressed and then released*/
 {
  SDL_PollEvent( &e );
 }
    
 SDL_DestroyRenderer(renderer);
 SDL_DestroyWindow(window);
 SDL_Quit();
 return 0;
}

/*
 This file is the Chastity's modification of an example from here:

 https://daywithstars.github.io/sdl2/geometry/2021/12/03/SDL2-new-geometry-rendering-SDL_RenderGeometry.html

 Unlike the original, this one is compatible with the C89 standard which Chastity always uses.

 Compile and run on Linux with this command:
 gcc -Wall -ansi -pedantic main.c -o main `sdl2-config --cflags --libs` -lm && ./main
*/

我在我的Github项目中有这个例子和更多的例子。

https://github.com/chastitywhiterose/SDL_Chaste_Triangle

只要有足够多的三角形,就可以绘制任何形状。因此,我制作了这个项目,以帮助我在未来制作游戏时使用。


虽然链接可能回答了问题,但规则要求答案必须是自包含的。您能否将最重要的部分编辑到答案本身中? - HolyBlackCat
1
太棒了,我弄清楚如何在回答中分享代码了。我必须选择文本并使用CTRL+K。我是Stack Overflow的新手,只是因为SDL Triangle问题才加入的。我不怪问题发起人不想去操作OpenGL! - Chandler Isaac Klebs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接