SDL2垂直同步

最近学习SDL2中用到了垂直同步这一技术,实现动画的处理,通过百科可知,垂直同步又称场同步,场信号一般是50Hz,或者60Hz,从CRT显示器的显示原理来看,单个像素组成了水平扫描线,水平扫描线在垂直方向的堆积形成了完整的画面,电脑中图象是通过显卡来显示的,比较高端的显卡生成图像更快些,垂直同步这一技术是让显卡生成图象时收到垂直同步信号的制约,使得画面更流畅些。如果没有垂直同步,图像速度就会提升,但是也会导致画面不流畅,出现跳帧现象,画面有撕裂现象,一般都是建议开启垂直同步,使得画面看起来狠舒适,

下面代码是加上垂直同步的代码

//Using SDL and standard IO
#include 
#include 
#include 
#include 
#include 
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
#define NUMBER_CLIPS 16
bool init();
bool loadMedia();
void close();

SDL_Texture* loadTexture(char* path);
SDL_Window* gWindow = NULL;
SDL_Texture* gSpriteSheetTexture = NULL;
SDL_Renderer* gRenderer = NULL;
SDL_Rect gSpriteClips[NUMBER_CLIPS];
SDL_Rect* currRect = NULL;
bool init()
{
    bool success = true;
    //Initialize SDL
	if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
	{
		printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
		success = false;
	}
	else
	{
		//Create window
		gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
		if( gWindow == NULL )
		{
			printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
			success = false;
		}
		else
		{
		    int imgFlag = IMG_INIT_PNG;
            gRenderer = SDL_CreateRenderer(gWindow,-1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
            if(gRenderer == NULL)
            {
                printf("Renderer counld'nt be create SDLError:%s\n", SDL_GetError());
                success = false;
            }

		    if(!(IMG_Init(imgFlag) & imgFlag))
            {
                printf("SDL_image could not initialize! SDL_image Error:%s\n",IMG_GetError());
                success = false;
            }

		}
	}
	return success;
}
bool loadMedia()
{
    bool success = true;
    char i,j;
    //Load splash image
    gSpriteSheetTexture = loadTexture("walk.png");
    if(gSpriteSheetTexture == NULL)
    {
        printf("Unable to load default image %s! SDL Error:%s\n","walk.png",SDL_GetError());
        success = false;
    }
    else
    {
        for(i = 0; i < 4;i++)
        {
            for(j = 0; j < 4; j++)
            {
                gSpriteClips[4*i+j].x = 32*j;
                gSpriteClips[4*i+j].y = 48*i;
                gSpriteClips[4*i+j].w = 32;
                gSpriteClips[4*i+j].h = 48;
            }
        }
    }

    return success;
}
SDL_Texture* loadTexture(char * path)
{
    SDL_Texture* texture = NULL;
    SDL_Surface* loadedSurface = IMG_Load(path);
    if(loadedSurface == NULL)
    {
        printf("Unable to load image %s! SDL Error:%s\n",path,IMG_GetError());

    }
    else
    {
        texture = SDL_CreateTextureFromSurface(gRenderer,loadedSurface);
        if(texture == NULL)
        {
            printf("Unable to optimize image %s!, SDL Error %s\n",path, SDL_GetError());
        }
        SDL_FreeSurface(loadedSurface);
    }
    return texture;
}
void close()
{
    SDL_DestroyTexture(gSpriteSheetTexture);
    gSpriteSheetTexture = NULL;
    SDL_DestroyRenderer(gRenderer);
    gRenderer = NULL;
    SDL_DestroyWindow(gWindow);
    gWindow = NULL;
    IMG_Quit();
    SDL_Quit();
}
int main( int argc, char* args[] )
{
    int frame = 0;
    if(!init())
    {
        printf("Failed to Initialized!\n");
    }
    else
    {
        if(!loadMedia())
        {
            printf("Failed to load image!\n");
        }
        else
        {
            bool quit = false;
            SDL_Event e;

            SDL_Rect distRect = {SCREEN_WIDTH/2 - 16, SCREEN_HEIGHT/2 - 24, 32,48};
            while(!quit)
            {
                while(SDL_PollEvent(&e) != 0)
                {
                    if(e.type == SDL_QUIT)
                    {
                        quit = true;
                    }
                }
                SDL_SetRenderDrawColor(gRenderer,0xff,0xff,0xff,0xff);
                SDL_RenderClear(gRenderer);

                currRect = &gSpriteClips[frame/8];
                SDL_RenderCopy(gRenderer, gSpriteSheetTexture,currRect,&distRect);
                SDL_RenderPresent(gRenderer);
                frame++;
                if(frame/8 >= NUMBER_CLIPS)
                {
                    frame = 0;
                }
            }
        }
    }
    close();
	return 0;
}

运行的结果如下

SDL2垂直同步_第1张图片

画面比较流畅,当我们去掉创建渲染器的SDL_RENDERER_PRESENTVSYNC标志时,即

gRenderer = SDL_CreateRenderer(gWindow,-1, SDL_RENDERER_ACCELERATED);

再次运行的结果如下:

SDL2垂直同步_第2张图片

明显可以看出,后者速率很快,但是运行轨迹没有前者流畅,我的监视器刷新频率是60Hz,gif动画的录制时间间隔是30ms,虽然不晓得 SDL_RenderPresent(SDL_Renderer* renderer)具体是怎么实现的,我想刷新时可能会在里面等待垂直同步信号到来吧。而且SDL_Renderer这个结构体看不到也。。。

参考链接:http://lazyfoo.net/tutorials/SDL/14_animated_sprites_and_vsync/index.php

你可能感兴趣的:(SDL,Windows)