linux中opengl实现文字显示的方法

前段时间为了弄毕业设计,要用opengl显示文字,在网上找了很多方法,但大都是在windows下的实现方法,几乎没有linux下的,找了很久才找到。

首先,opengl本身是没有显示文字的函数的,必须要借助其他的库,linux下有SDL,利用SDL本身的编程是可以显示汉字的,但是如何将opengl和SDL融合显示汉字!这就是难点所在!

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_opengl.h>
#include <wchar.h>
#include <iconv.h>
         
#define TRUE (-1)
#define FALSE 0
typedef  int BOOL;
         
         
const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 400;
const int SCREEN_BPP = 32;
         
SDL_Surface *image = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *message = NULL;
         
TTF_Font *font = NULL;
SDL_Color textColor = { 255, 0, 0 };
SDL_Color blackColor = { 0,0,0 };
         
BOOL init()
{
         
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
    {
         return FALSE;
    }
         
    //screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL );
         
    if( screen == NULL )
    {
         return FALSE;
    }
         
    //Initialize SDL_ttf
    if( TTF_Init() == -1 )
        return FALSE;
         
    SDL_WM_SetCaption( "show Chinese text @bluedrum", NULL );
    //If everything initialized fine
    return TRUE;
}
         
void clean_up()
{
         
    SDL_FreeSurface( image );
    SDL_FreeSurface( message );
    TTF_CloseFont( font );          //Close the font that was used
    TTF_Quit();             //Quit SDL_ttf
    SDL_Quit();         //Quit SDL
}
         
SDL_Surface *load_image( char * filename )
{
    SDL_Surface* loadedImage = NULL;
             
    SDL_Surface* optimizedImage = NULL;
             
    loadedImage = IMG_Load( filename);
             
    if( loadedImage != NULL )
    {
        optimizedImage = SDL_DisplayFormat( loadedImage );
                 
        SDL_FreeSurface( loadedImage );
    }
             
    return optimizedImage;
}
         
void SDL_GL_Enter2DMode()
{
    SDL_Surface *screen = SDL_GetVideoSurface();
         
    /* Note, there may be other things you need to change,
       depending on how you have your OpenGL state set up.
    */
    glPushAttrib(GL_ENABLE_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glEnable(GL_TEXTURE_2D);
         
    /* This allows alpha blending of 2D textures with the scene */
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glViewport(0, 0, screen->w, screen->h);
         
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
         
    glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
         
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
         
void SDL_GL_Leave2DMode()
{
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
         
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glPopAttrib();
}
         
/* Quick utility function for texture creation */
static int power_of_two(int input)
{
    int value = 1;
         
    while ( value < input ) {
        value <<= 1;
    }
    return value;
}
         
GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord)
{
    GLuint texture;
    int w, h;
    SDL_Surface *image;
    SDL_Rect area;
    Uint32 saved_flags;
    Uint8  saved_alpha;
         
    /* Use the surface width and height expanded to powers of 2 */
    w = power_of_two(surface->w);
    h = power_of_two(surface->h);
    texcoord[0] = 0.0f;         /* Min X */
    texcoord[1] = 0.0f;         /* Min Y */
    texcoord[2] = (GLfloat)surface->w / w;   /* Max X */
    texcoord[3] = (GLfloat)surface->h / h;   /* Max Y */
         
    image = SDL_CreateRGBSurface(
            SDL_SWSURFACE,
            w, h,
            32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
            0x000000FF,
            0x0000FF00,
            0x00FF0000,
            0xFF000000
#else
            0xFF000000,
            0x00FF0000,
            0x0000FF00,
            0x000000FF
#endif
               );
    if ( image == NULL ) {
        return 0;
    }
         
    /* Save the alpha blending attributes */
    saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
#if SDL_VERSION_ATLEAST(1, 3, 0)
    SDL_GetSurfaceAlphaMod(surface, &saved_alpha);
    SDL_SetSurfaceAlphaMod(surface, 0xFF);
#else
    saved_alpha = surface->format->alpha;
    if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
        SDL_SetAlpha(surface, 0, 0);
    }
#endif
         
    /* Copy the surface into the GL texture image */
    area.x = 0;
    area.y = 0;
    area.w = surface->w;
    area.h = surface->h;
    SDL_BlitSurface(surface, &area, image, &area);
         
    /* Restore the alpha blending attributes */
#if SDL_VERSION_ATLEAST(1, 3, 0)
    SDL_SetSurfaceAlphaMod(surface, saved_alpha);
#else
    if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
        SDL_SetAlpha(surface, saved_flags, saved_alpha);
    }
#endif
         
    /* Create an OpenGL texture for the image */
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D,
             0,
             GL_RGBA,
             w, h,
             0,
             GL_RGBA,
             GL_UNSIGNED_BYTE,
             image->pixels);
    SDL_FreeSurface(image); /* No longer needed */
         
    return texture;
}
         
         
         
int main(int argc,char * argv[])
{
    char a[] = "abc";
    char *img_name = "./bk.jpg";
    Uint16 msg[1024] = {0xc2d0,0xcbce,0xcce5,0};
    wchar_t *msg1 = L"新宋体";
    int w,h,done;
    int i=0;
    GLuint texture;
    GLfloat texcoord[4];
    GLfloat texMinX, texMinY;
    GLfloat texMaxX, texMaxY;
    SDL_Event event;
         
    //msg2 = ConvertUnicodeToUtf8(msg1);
             
    init();
         
    if(argc > 1)
    {
        strncpy(img_name,argv[1],sizeof(img_name)-1);
        img_name[sizeof(img_name)-1] = 0;
         
    }
         
    font  = TTF_OpenFont("./simfang.ttf",20);
    if(font == NULL)
    {
        fprintf(stderr,"font open failure %s\n",SDL_GetError());
        clean_up();
        exit(-1);
    }
         
    image =load_image(img_name);
    TTF_SetFontStyle(font,TTF_STYLE_BOLD |  TTF_STYLE_ITALIC);
    message = TTF_RenderUNICODE_Solid( font, msg1, textColor );
    //message = TTF_RenderText_Solid(font,"ABCEFGHIJK",blackColor);
         
    w = message->w;
    h = message->h;
    //w = image->w;
    //h = image->h;
         
    texture = SDL_GL_LoadTexture(message, texcoord);
         
        /* Make texture coordinates easy to understand */
    texMinX = texcoord[0];
    texMinY = texcoord[1];
    texMaxX = texcoord[2];
    texMaxY = texcoord[3];
         
        /* Initialize the GL state */
    glViewport( 0, 0, screen->w, screen->h );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );
         
    glOrtho( -2.0, 2.0, -2.0, 2.0, -20.0, 20.0 );
         
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity( );
         
    glEnable(GL_DEPTH_TEST);
         
    glDepthFunc(GL_LESS);
         
    glShadeModel(GL_SMOOTH);
         
        /* Clear the screen */
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         
    /* Show the text on the screen 关键部分*/
    SDL_GL_Enter2DMode();
    glBindTexture(GL_TEXTURE_2D, texture);
    glBegin(GL_TRIANGLE_STRIP);
    glTexCoord2f(texMinX, texMinY); glVertex2i(50,   50  );
    glTexCoord2f(texMaxX, texMinY); glVertex2i(50+w, 50  );
    glTexCoord2f(texMinX, texMaxY); glVertex2i(50,   50+h);
    glTexCoord2f(texMaxX, texMaxY); glVertex2i(50+w, 50+h);
    glEnd();
    SDL_GL_Leave2DMode();
         
    SDL_GL_SwapBuffers( );
         
         
    if(SDL_Flip(screen) == -1)
        return -1;
         
        /* Wait for a keystroke,input esc to quit */
    done = 0;
    while ( ! done ) {
        while ( SDL_PollEvent(&event) ) {
            switch (event.type) {
                case SDL_KEYDOWN:
                case SDL_QUIT:
                done = 1;
                break;
                default:
                break;
            }
        }
    }
    //SDL_Delay(3000);
         
    clean_up();
         
}

编译用gcc test.c -o test -lSDL_image -lSDL_ttf -lglut -finput-charset='gbk' -fshort-wchar

前面几个参数是调用库, -finput-charset='gbk' -fshort-wchar参数是为了解决汉字的编码问题

其中bk.jpg是图片文件./simfang.tff是汉字库,可以在网上下。

代码分析,与其它的opengl函数使用来说就多了几个函数,SDL_GL_LoadTexture;SDL_GL_Enter2DMode;SDL_GL_Leave2DMode这3个函数,它们是实现汉字显示的关键函数,函数之间相互独立,可以拷过去直接用。其根本原理还是使用了opengl的纹理映射的原理;图片和汉字的用法也是一样的。PS:前面做的时候,看到过中科院一个硕士的方法,看了半天论文也没发现具体的实现方法,汗!!最后还是在SDL的官方文件中找到,再自己研究的方法。

opengl和SDL的融合还是在 SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL )中的SDL_OPENGL宏,否则就是SDL的显示了。如果能用SDL加opengl来作界面和游戏的话,还是很给力的。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔波的IT人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值