首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(译)SDL编程入门(7)纹理加载和渲染

(译)SDL编程入门(7)纹理加载和渲染

作者头像
arcticfox
发布2020-09-27 10:19:53
9630
发布2020-09-27 10:19:53
举报

纹理加载和渲染

SDL2 的一个主要新功能是纹理渲染 API。这为您提供了快速、灵活的基于硬件的渲染。在本教程中,我们将使用这种新的渲染技术。

//将单个图像作为纹理加载
SDL_Texture* loadTexture( std::string path );

//我们要渲染的窗口
SDL_Window* gWindow = NULL;

//窗口渲染器
SDL_Renderer* gRenderer = NULL;

//当前显示的纹理
SDL_Texture* gTexture = NULL;

SDL中的纹理有自己的数据类型,直观地称为SDL_Texture。当我们处理SDL纹理时,你需要一个SDL_Renderer来将它渲染到屏幕上,这就是为什么我们要声明一个名为 "gRenderer "的全局渲染器。

你也可以看到,我们有一个loadTexture的新图像加载例程和一个我们将要加载的全局声明的纹理。

        //创建窗口
        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
        {
            //创建窗口的渲染器
            gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
            if( gRenderer == NULL )
            {
                printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
                success = false;
            }
            else
            {
                //初始化渲染器颜色
                SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );

                //初始化PNG加载
                int imgFlags = IMG_INIT_PNG;
                if( !( IMG_Init( imgFlags ) & imgFlags ) )
                {
                    printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
                    success = false;
                }
            }
        }

在我们创建了窗口之后,我们必须为我们的窗口创建一个渲染器,这样我们就可以在上面渲染纹理,幸运的是这很容易通过调用SDL_CreateRenderer[1]来完成。幸运的是,只要调用SDL_CreateRenderer就可以轻松完成。

创建渲染器后,我们要使用SDL_SetRenderDrawColor[2]来初始化渲染颜色。这可以控制各种渲染操作使用什么颜色。

SDL_Texture* loadTexture( std::string path ){
    //最终的纹理
    SDL_Texture* newTexture = NULL;

    //在指定路径加载图像
    SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
    if( loadedSurface == NULL )
    {
        printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
    }
    else
    {
        //用表面像素创建纹理
        newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
        if( newTexture == NULL )
        {
            printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
        }

        //Get rid of old loaded surface
        SDL_FreeSurface( loadedSurface );
    }

    return newTexture;
}

我们的纹理加载函数看起来和之前基本相同,只是现在我们没有将加载的表面转换为显示格式,而是使用SDL_CreateTextureFromSurface[3]从加载的表面中创建一个纹理。和之前一样,这个函数从一个现有的表面创建一个新的纹理,这意味着和之前一样,我们必须释放加载的表面,然后返回加载的纹理。

bool loadMedia(){
    //Loading success flag
    bool success = true;

    //Load PNG texture
    gTexture = loadTexture( "07_texture_loading_and_rendering/texture.png" );
    if( gTexture == NULL )
    {
        printf( "Failed to load texture image!\n" );
        success = false;
    }

    return success;
}

void close(){
    //Free loaded image
    SDL_DestroyTexture( gTexture );
    gTexture = NULL;

    //Destroy window
    SDL_DestroyRenderer( gRenderer );
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;
    gRenderer = NULL;

    //Quit SDL subsystems
    IMG_Quit();
    SDL_Quit();
}

由于纹理加载与我们的图像加载函数一起被抽象化了,所以loadMedia()函数的工作原理和之前差不多。

在我们的清理函数中,我们必须记住使用SDL_DestroyTexture[4]来deallocate我们的纹理。

             //While application is running
            while( !quit )
            {
                //Handle events on queue
                while( SDL_PollEvent( &e ) != 0 )
                {
                    //User requests quit
                    if( e.type == SDL_QUIT )
                    {
                        quit = true;
                    }
                }

                //清空屏幕
                SDL_RenderClear( gRenderer );

                //将纹理渲染到屏幕上
                SDL_RenderCopy( gRenderer, gTexture, NULL, NULL );

                //更新屏幕
                SDL_RenderPresent( gRenderer );
            }

在事件循环之后的主循环中,我们调用SDL_RenderClear[5]。这个函数用上次SDL_SetRenderDrawColor设置的颜色填充屏幕。

清空屏幕后,我们用SDL_RenderCopy[6]渲染纹理。纹理渲染完成后,我们仍然需要更新屏幕,但由于我们没有使用SDL_Surfaces来渲染,所以不能使用SDL_UpdateWindowSurface。相反,我们必须使用SDL_RenderPresent[7]

这里[8]下载本教程的媒体和源代码。

原文链接[9]

关注我的公众号:编程之路从0到1

参考资料

[1]

SDL_CreateRenderer: https://wiki.libsdl.org/SDL_CreateRenderer

[2]

SDL_SetRenderDrawColor: https://wiki.libsdl.org/SDL_SetRenderDrawColor

[3]

SDL_CreateTextureFromSurface: https://wiki.libsdl.org/SDL_CreateTextureFromSurface

[4]

SDL_DestroyTexture: https://wiki.libsdl.org/SDL_DestroyTexture

[5]

SDL_RenderClear: https://wiki.libsdl.org/SDL_RenderClear

[6]

SDL_RenderCopy: https://wiki.libsdl.org/SDL_RenderCopy

[7]

SDL_RenderPresent: https://wiki.libsdl.org/SDL_RenderPresent

[8]

这里: http://www.lazyfoo.net/tutorials/SDL/07_texture_loading_and_rendering/07_texture_loading_and_rendering.zip

[9]

原文链接: http://www.lazyfoo.net/tutorials/SDL/07_texture_loading_and_rendering/index.php

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程之路从0到1 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 纹理加载和渲染
    • 参考资料
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档