SDL2系列教程5-几何渲染

GPU渲染

到目前为止,您一直在使用软件或CPU渲染。这意味着要将表面blit到窗口,计算机的CPU必须遍历每个像素,调整并复制值。

另一方面,硬件渲染利用了计算机的GPU(图形处理单元)。硬件渲染可以比软件快一个数量级,因为GPU针对这些精确的工作负载进行了优化。GPU不是单独通过像素数据,而是可以并行执行计算,大幅提高吞吐量。

渲染器

SDL结构SDL_Renderer表示渲染上下文。这意味着它包含与渲染相关的所有当前设置,以及有关如何渲染当前帧的说明。在程序中,您将使用SDL_SetRenderDrawColor()等函数更改上下文中的设置,并使用SDL_RenderDrawPoint()等函数执行渲染操作。

要创建渲染上下文,可以使用函数SDL_CreateWindowAndRenderer()SDL_CreateRenderer()。前者完成了您的期望:它同时创建窗口和渲染器。后者要求您首先创建一个窗口(因为窗口必须是一个参数),但允许对初始化进行更精细的控制。

SDL_Window* window;
SDL_Renderer* renderer;

int result = SDL_CreateWindowAndRenderer( 640, 480, NULL, &window, &renderer );
if ( result != 0 ) {
	cout << "Failed to create window and renderer: " << SDL_GetError() << endl;
}

我们不再使用表面来表示窗口。相反,渲染上下文绘制到后备缓冲区,然后在每个帧的末尾显示在窗口上。因此,您不能再调用SDL_UpdateWindowSurface()。相反,您使用SDL_RenderPresent()。此函数告诉渲染器在其窗口上显示其操作。

SDL_SetRenderDrawColor( renderer, 255, 255, 255, 255 );
SDL_RenderDrawPoint( renderer, 100, 100 );

// Update window
SDL_RenderPresent( renderer );

清除渲染器

清除渲染器会将窗口重置为颜色 - 这相当于在整个窗口上显示矩形。您应该在每帧之后清除窗口,否则即使移动,绘图也会在帧之间保持不变。

正如您所期望的那样,函数SDL_RenderClear()用于此目的。唯一的参数是渲染器; 关联的窗口将被清除为当前颜色。

SDL_RenderClear( renderer );

// do drawing

SDL_RenderPresent( renderer );

绘制设置

绘图状态包含在渲染上下文中,因此SDL提供了几个调整它的函数。要更改绘图颜色(影响绘图函数和SDL_RenderClear()),请使用函数SDL_SetRenderDrawColor()。它的使用非常简单 - 只需传递R,G,B和A颜色值。要获取当前颜色,请使用函数SDL_GetRenderDrawColor()

SDL_SetRenderDrawColor( renderer, 255, 255, 255, 255 ); // Set color to solid white

SDL_RenderClear( renderer ); // Clear the screen to solid white

要设置绘图混合模式,请使用函数SDL_SetRenderDrawBlendMode()。甲的BlendMode是简单地绘制与alpha(透明度)纹理的方法的数据-例如,默认的BlendMode简单地融汇基于α值的颜色。但是,SDL还支持添加和调制混合,这极大地影响了最终图像。我鼓励你自己测试一下。要获取当前的blendmode,请使用函数SDL_GetRenderDrawBlendMode()

SDL_SetRenderDrawBlendMode( renderer, SDL_BLENDMODE_ADD ); // Switch to additive blending

SDL_RenderDrawLine( renderer, 0, 0, 100, 100 ); // Draw with additive blending

这些设置和更多设置在SDL wiki上的CategoryRender下进行分类

绘制

正如我在本节中所提到的,SDL提供了几种绘制基本形状的功能 - 即点,线,矩形和填充矩形。这些函数全部按照您的期望使用:点和线函数只是取形状的屏幕坐标,矩形函数采用具有相同数据的SDL_Rect。

 

所有这些功能和更多功能都归类于SDL wiki上的CategoryRender

SDL_SetRenderDrawColor( renderer, 0, 0, 255, 255 ); // Draw in solid blue

SDL_RenderDrawLine( renderer, 10, 10, 50, 25 ); // Draw a line

SDL_Rect r;
r.x = 150;
r.y = 25;
r.h = 75;
r.w = 120;

SDL_RenderFillRect( renderer, &r ); // Draw a filled rectangle

// etc

关掉

关闭与软件渲染几乎完全相同,但现在必须使用函数SDL_DestroyRenderer()在关闭窗口之前释放渲染器。你仍然以同样的方式释放表面。

SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );

renderer = NULL;
window = NULL;

实例代码:

    
#include <iostream>
#include <SDL2/SDL.h>

using namespace std;

bool init();
void kill();
bool loop();

// Pointers to our window and renderer
SDL_Window* window;
SDL_Renderer* renderer;

int main(int argc, char** args) {

    if ( !init() ) return 1;

    while ( loop() ) {
        // wait before processing the next frame
        SDL_Delay(10); 
    }

    kill();
    return 0;
}

bool loop() {

    static const unsigned char* keys = SDL_GetKeyboardState( NULL );

    SDL_Event e;
    SDL_Rect r;
    // For mouse rectangle (static to presist between function calls)
    static int mx0 = -1, my0 = -1, mx1 = -1, my1 = -1;

    // Clear the window to white
    SDL_SetRenderDrawColor( renderer, 255, 255, 255, 255 );
    SDL_RenderClear( renderer );

    // Event loop
    while ( SDL_PollEvent( &e ) != 0 ) {
        switch ( e.type ) {
            case SDL_QUIT:
                return false;
            case SDL_MOUSEBUTTONDOWN:
                mx0 = e.button.x;
                my0 = e.button.y;
                break;
            case SDL_MOUSEMOTION:
                mx1 = e.motion.x;
                my1 = e.motion.y;
                break;
            case SDL_MOUSEBUTTONUP:
                mx0 = my0 = mx1 = my1 = -1;
                break;
        }
    }

    // Set drawing color to black
    SDL_SetRenderDrawColor( renderer, 0, 0, 0, 255 );

    // Test key states - this could also be done with events
    if ( keys[SDL_SCANCODE_1] ) {
        SDL_RenderDrawPoint( renderer, 10, 10 );
    }
    if ( keys[SDL_SCANCODE_2] ) {
        SDL_RenderDrawLine( renderer, 10, 20, 10, 100 );
    }
    if ( keys[SDL_SCANCODE_3] ) {
        r.x = 20;
        r.y = 20;
        r.w = 100;
        r.h = 100;
        SDL_RenderFillRect( renderer, &r );
    }

    // Render mouse rectangle
    if ( mx0 != -1 ) {
        r.x = mx0;
        r.y = my0;
        r.w = mx1 - mx0;
        r.h = my1 - my0;
        SDL_RenderDrawRect( renderer, &r );
    }

    // Update window
    SDL_RenderPresent( renderer );

    return true;
}

bool init() {
    // See last example for comments
    if ( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
        cout << "Error initializing SDL: " << SDL_GetError() << endl;
        return false;
    } 

    window = SDL_CreateWindow( "Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 150, 150, SDL_WINDOW_SHOWN );
    if ( !window ) {
        cout << "Error creating window: " << SDL_GetError()  << endl;
        return false;
    }

    renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
    if ( !renderer ) {
        cout << "Error creating renderer: " << SDL_GetError() << endl;
        return false;
    }

    SDL_SetRenderDrawColor( renderer, 255, 255, 255, 255 );
    SDL_RenderClear( renderer );
    return true;
}

void kill() {
    // Quit
    SDL_DestroyRenderer( renderer );
    SDL_DestroyWindow( window );
    SDL_Quit();
}

Makefile修改文件名即可;

使用鼠标测试,可以绘制出矩形;

猜你喜欢

转载自blog.csdn.net/cyf15238622067/article/details/82907362