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修改文件名即可;
使用鼠标测试,可以绘制出矩形;