精华内容
下载资源
问答
  • 位图字体

    千次阅读 2014-05-30 09:45:01
    使用位图字体比起使用图形字体(贴图)看起来不止强100倍。你可以随时改变显示在屏幕上的文字,而且用不着为它们逐个制作贴图。只需要将文字定位,再使用我最新的gl命令就可以在屏幕上显示文字了。 我尽可能试着将...

    图像字体A:

    这一课我们将创建一些基于2D图像的字体,它们可以缩放,但不能旋转,并且总是面向前方,但作为基本的显示来说,我想已经够了。

    使用位图字体比起使用图形字体(贴图)看起来不止强100倍。你可以随时改变显示在屏幕上的文字,而且用不着为它们逐个制作贴图。只需要将文字定位,再使用我最新的gl命令就可以在屏幕上显示文字了。

    我尽可能试着将命令做的简单。你只需要敲入glPrint("Hello") 。它是那么简单。

    一个小注释,这段代码是专门针对Windows写的,它使用了Windows的wgl函数来创建字体。

    我们从第十课的典型代码开始,最后加上math.h头文件,这样我们就可以使用SIN和COS函数在屏幕中移动文字了。

     

    另外,我们还要添加3个变量。base将保存我们创建的第一个显示列表的编号。每个字符都需要有自己的显示列表。例如,字符‘A’在显示列表中是65,‘B’是66,‘C’是67,等等。所以,字符‘A’应保存在显示列表中的base + 65这个位置。

    然后添加两个计数器(cnt1 和 cnt2),它们采用不同的累加速度,通过SIN和COS函数来改变文字在屏幕上的位置。在屏幕上创造出一种看起来像是半随机的移动方式。同时,我们用这两个计数器来改变文字的颜色(后面会进一步解释)。

    1. //第十一课图像字体  
    2. GLuint  base;           // 绘制字体的显示列表的开始位置  
    3. GLfloat cnt1;           // 字体移动计数器1  
    4. GLfloat cnt2;           // 字体移动计数器2  


    构建真实字体


    下面这段代码用来构建真实的字体,这也是最难写的一部分代码。

    ‘HFONT font’告诉Windows我们将要使用一个Windows字体。Oldfont用来存放字体。

    接下来我们在定义base的同时使用glGenLists(96)创建了一组共96个显示列表。

    1. GLvoid COpenglbaseView::BuildFont(GLvoid)  
    2. {  
    3.     HFONT   font;                       // 字体句柄  
    4.     HFONT   oldfont;                        // 旧的字体句柄  
    5.       
    6.     base = glGenLists(96);                  // 创建96个显示列表  


    下面该有趣的部分了,我们将创建属于自己的字体。我们从指定字体的大小开始,你会注意到它是一个负数,我们通过加上一个负号来告诉Windows寻找一个基于CHARACTER高度的字体。如果我们使用一个正数,就是寻找一个与基于CELL的高度相匹配的字体。

    1. font = CreateFont(  -24,                    // 字体高度  
    2.     0,              // 字体宽度 Windows就会使用默认值        
    3.     0,              // 字体的旋转角度 Angle Of Escapement  
    4.     0,              // 字体底线的旋转角度Orientation Angle用于指定每个字的底边和显示设备的X轴之间的角度,每个单位是十分之一个角度  
    5.     FW_BOLD,                // 字体的重量 FW_DONTCARE是0, FW_NORMAL是400, FW_BOLD是700 and FW_BLACK是900。值越大,字体就越粗。    
    6.     FALSE,              // 是否使用斜体  
    7.     FALSE,              // 是否使用下划线  
    8.     FALSE,              // 是否使用删除线    
    9.     ANSI_CHARSET,           // 设置字符集  
    10.     OUT_TT_PRECIS,          // 输出精度   
    11.     CLIP_DEFAULT_PRECIS,        // 裁剪精度  
    12.     ANTIALIASED_QUALITY,        // 输出质量   
    13.     FF_DONTCARE|DEFAULT_PITCH,      // Family And Pitch   
    14. "Courier New");         // 字体名称  打开Microsoft Word找一个你喜欢的字体。将‘Courier New’替换为你想用的字体的名字,你就可以使用它了。(中文还不行,需要别的方法)  
    15.       


     现在,选择我们刚才创建的字体。Oldfont将指向被选择的对象。然后我们从第32个字符(空格)开始建立96个显示列表。如果你愿意,也可以建立所有256个字符,只要确保使用glGenLists建立256个显示列表就可以了。然后我们将oldfont对象指针选入hDC并且删除font对象。

    1.       
    2.  oldfont=(HFONT)SelectObject(m_pDC->GetSafeHdc(),font); // 选择我们需要的字体  
    3.  wglUseFontBitmaps(m_pDC->GetSafeHdc(),32,96,base);  //创建96个显示列表,绘制ASCII码为32-128的字符 
    4. //可以使用wglUseFontBitmaps函数来批量的产生显示字符用的显示列表。
    5.  SelectObject(m_pDC->GetSafeHdc(),oldfont);  //选择原来的字体  
    6.  DeleteObject(font);         //删除字体  
    7.   
    8. }  

    接下来的代码很简单。它在内存中从base开始删除96个显示列表。我不知道Windows是否会做这些工作,但还是保险为好。

    1. GLvoid COpenglbaseView::KillFont(GLvoid)  
    2. {  
    3.     glDeleteLists(base,96);     //删除96个显示列表  
    4.   
    5. }  

    // 自定义GL输出字体函数

    然后我们将GL_LIST_BIT压入属性堆栈,它会防止glListBase影响到我们的程序中的其它显示列表。

    GlListBase(base-32)是一条有些难解释的命令。比如说要写字母‘A’,它的相应编号为65。如果没有glListBase(base-32)命令,OpenGL就不知道到哪去找这个字母。它会在显示列表中的第65个位置找它,但是,假如base的值等于1000,那么‘A’的实际存放位置就是1065了。所以通过base设置一个起点,OpenGL就知道到哪去找到正确的显示列表了。减去32是因为我们没有构造过前32个显示列表,那么就跳过它们好了。于是,我们不得不通过从base的值减去32,作为偏移的基准来让OpenGL知道这一点。我希望这些有意义。
    GlCallLists是一个很有趣的命令。它可以同时将多个显示列表的内容显示在屏幕上。

    下面的代码做后续工作。首先,它告诉OpenGL我们将要在屏幕上显示出显示列表中的内容。

    strlen(text)函数用来计算我们将要显示在屏幕上的文字的长度。

    然后,OpenGL需要知道我们允许发送给它的列表的最大值。我们不能发送长度大于255的字符串。这个字符列表的参数被当作一个无符号字符数组处理,它们的值都介于0到255之间。

    最后,我们通过传递str(它指向我们的字符串)来告诉OpenGL显示的内容。

    也许你想知道为什么字符不会彼此重叠堆积在一起。那时因为每个字符的显示列表都知道字符的右边缘在那里,在写完一个字符后,OpenGL自动移动到刚写过的字符的右边,在写下一个字或画下一个物体时就会从GL移动到的最后的位置开始,也就是最后一个字符的右边。

    最后,我们将GL_LIST_BIT属性弹出堆栈,将GL恢复到我们使用glListBase(base-32)设置base那时的状态。

     

    1. GLvoid COpenglbaseView::glPrint(unsigned int base, char *str)  
    2. {  
    3.     if((base==0)||(str==NULL))  
    4.         return ;  
    5.     glPushAttrib(GL_LIST_BIT); 
    6. /*******************************************************************************************************
    7. GL依据相关性将其属性划分为20组。例如,所有的多边形属性位于GL_POLYGON_BIT组中,

      所有的直线属性位于GL_LINE_BIT中,我们可以将多组属性或者全部属性(GL_ALL_ATTRIBUTE_BITS)

      通过函数glPushAttrib压入属性堆栈中,恢复则用glPopAttrib。

    8. 与glPushMatrix的区别:

    9. glPushMatrix操作的对象是矩阵,主要是对画图的平移、旋转、放缩等进行操作;

    10. glPushAttrib操作的对象是各种属性,对绘制的各种属性(颜色等),进行操作。

      *********************************************************************************************************/
    11.     glListBase(base-32);  
    12.     glCallLists((GLsizei)strlen(str),GL_UNSIGNED_BYTE,str);  
    13.     glPopAttrib();  
    14. }  
    在初始化代码中添加BuildFont( );
    1. BOOL COpenglbaseView::InitializeOpenGL(CDC *pDC)  
    2. {  
    3.     m_pDC=pDC;  
    4.     if(!SetupPixelFormat())  
    5.         return FALSE;  
    6.     m_hRC=::wglCreateContext(m_pDC->GetSafeHdc());//产生一个新的opengl绘图描述表使之适合在参数hdc给出的设备上画图    
    7.     ::wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC);  
    8.       
    9.     SetLight();//设置光照环境  
    10.     myInit();//设置绘图环境  
    11.     BuildFont();  
    12.   
    13.   
    14.     return TRUE;  
    15. }  

    绘图代码

    1. BOOL COpenglbaseView::RenderScene()  
    2. {  
    3.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         // 清除屏幕及深度缓存  
    4.     glLoadIdentity();  
    5.     glTranslatef(0.0f,0.0f,-1.0f);              // 移入屏幕一个单位  
    6.     // 根据字体位置设置颜色  
    7.     glColor3f(1.0f*float(cos(cnt1)),1.0f*float(sin(cnt2)),1.0f-0.5f*float(cos(cnt1+cnt2)));   
    8.     // 设置光栅化位置,即字体的位置  
    9.     glRasterPos2f(-0.45f+0.05f*float(cos(cnt1)), 0.35f*float(sin(cnt2)));  
    10.     glPrint(base,"You are great!");     // 输出文字到屏幕  
    11.     cnt1+=0.051f;                       // 增加计数器值  
    12.     cnt2+=0.005f;  
    13.   
    14.     return TRUE;                        // 继续运行  
    15.   
    16. }  


     

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    补充解释

      函数原型:void glListBase(GLuintbase);

      函数功能:使得OpengL可以找到绘制对应字符的显示列表的位置。

      函数参数介绍:

      GLuint base 这个参数表示显示列表的基质。

      关于使用glListBase(GLuint base)进行字体创建有几点说明:

      void glListBase(GLuint base)的用法让人容易误解,还有为什么会使用glListBase(ListBase - 32)的情况;

      现在做一个解释:

      1 通过ListBase = glGenList(96);创建96个显示列表,从ListBase索引的位置开始的96个显示列表

      2 wglUseFrontBitmaps(hDC,32,96,ListBase);根据hDC中的字体属性从ASCII码32开始创建96个显示列表,(ASCII:32到127)而且这96个显示列表依次对应于显示列表从ListBase到ListBase+96.注意例如'A'的ASCII值是65那么对应的显示列表中位于ListBase+65

      3 glListBase(ListBase - 32);因为OpengL如果要寻找‘A’那么它会首先根据ListBase值+65得到‘A’的位置。但是wglUseFrontBitmaps()使得ListBase的值与ASCII为32的一样,所以就需要将ListBase的值减32与OpengL的查询方式保持一致。

      特别说明

      glListBase(ListBase - 32) 的说明 在没有这段命令之前ListBase的值对应着ASCII为32的显示列表

      如果使用glCallListBase()来显示字符时 如要显示‘A’ 那么他会从ListBase开始向后推进56位找到A

      也就是找到ListBase+56对应位置的字符 但是ListBase对应着ASCII为32 所以ListBase+56就不是

      A 所以 需要将ListBase-32 得到正确的基值。

      关于glListBase(GLuint base)的补充:

      1、如果想要正确理解glListBase的用法请先理解函数glCallLists(GLsizei n,GLenum type,const GLvoid *lists)的用法:此函数执行n个显示列表,执行数由n决定,所执行的列表索引是由当前显示列表基(由glListBase函数指定)指明的偏移量,加上由lists指向的数组中的有符号整数之和。

      2、正如上面glGenList(96)和wglUseFrontBitmap用法,但有点小错误(个人认为),即‘A'所对应的的显示列表中的位置应是ListBase+65-32,即ListBase+33,而不是ListBase+65。

      3、因为’A'的ASCII为65,而glListBase(GLuint base)中,base的默认值为0,所以如果不调用glListBase(ListBase - 32),而直接调用glCallLists(GLsizei n,GLenum type,const GLvoid *lists),么那它在想显示'A'时,调用的显示列表的索引应为base+65,即为65,这显然不是在'A'在显示列表中对应的位置ListBase+33,而当调用glListBase(ListBas - 32)后,则调用的显示列表的索引应为:ListBas - 32+65,即ListBase+33,正好便是字符'A'在显示列表中对应的位置。

    --------------------------------------------------------------------------------------------------------

     第十一课B:位图字体独立为单独的头文件和源文件

    OpenGL位图字体

     

     

       以下在第10课代码基础上进行修改。        点击打开链接   

     用GDI显示文字当然时非常容易,但是用OpenGL来显示文字则相对来说比较复杂一点,OpenGL中有三种字体:位图字体,轮廓字体,纹理映射字体。而采用位图字体可能时最简洁,最清楚的显示文本的方法,主要用到了"wiggle"函数wglUseFontBitmaps()来创建它们,也比较简单,此函数将从系统载入的字体文件中生成位图。下面时关于位图字体创建,使用的源代码例子:

    /OpenGLFontInit.h

    #ifndef _OPENGLFONTINIT_H_
    #define _OPENGLFONTINIT_H_

    unsigned int CreateBitmapFont(char *fontName,int fontSize,HDC g_HDC);
    void PrintString(unsigned int base,char *str);
    void ClearFont(unsigned int base);
    unsigned int InitializeFont(char *fontName,int fontSize,HDC g_HDC);

    #endif

    /OpenGLFontInit.cpp

    #include "stdafx.h"
    #include <gl\gl.h>
    #include <gl\glu.h>
    #include "OpenGLFontInit.h"

    unsigned int CreateBitmapFont(char *fontName,int fontSize,HDC g_HDC)
    {
    HFONT hFont;
    unsigned int base;
    base = glGenLists(96);

    hFont=CreateFont(fontSize,0,0,0,FW_BOLD,FALSE,FALSE,FALSE,
                   ANSI_CHARSET,OUT_TT_PRECIS,
                   CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,
          FF_DONTCARE|DEFAULT_PITCH,
          fontName);
    if(!hFont)
       return 0;
    SelectObject(g_HDC,hFont);
    wglUseFontBitmaps(g_HDC,32,96,base);
        return base;
    }

    void PrintString(unsigned int base,char *str)
    {
    if((base==0)||(str==NULL))
       return ;

    glPushAttrib(GL_LIST_BIT);
    glListBase(base-32);
    glCallLists((GLsizei)strlen(str),GL_UNSIGNED_BYTE,str);
    glPopAttrib();
    }

    void ClearFont(unsigned int base)
    {
    if(base!=0)
       glDeleteLists(base,96);
    }

    unsigned int InitializeFont(char *fontName,int fontSize,HDC g_HDC)
    {
    return CreateBitmapFont(fontName,fontSize,g_HDC);
    }

    例子:在opengl配置好的MFC单文档中使用opengl位图字体

    1.在视图源文件中#include "OpenGLFontInit.h",并且创建一个变量:

            unsigned int listBase;//创建一个字体显示列表的基准ID

    2.在视图源文件中的InitializeOpenGL(CDC *pDC)函数中添加:

           listBase=InitializeFont("宋体",20,wglGetCurrentDC());

    1. listBase=InitializeFont("Courier New",-24,m_pDC->GetSafeHdc());//不支持中文字体  
    2.  SetLight();//设置光照环境  
    3.  myInit();//设置绘图环境  

    3.最后就可以在视图源文件的RenderScene()函数中使用。如:

    进入屏幕的深度不同,glRasterPos可调节的精度就不一样。

           

    1. BOOL COpenglbaseView::RenderScene()  
    2. {  
    3.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         // 清除屏幕及深度缓存     
    4.     glLoadIdentity();    
    5.     glTranslatef(0.0f,0.0f,-1.0f);              // 移入屏幕一个单位     
    6.     // 根据字体位置设置颜色     
    7.     glColor3f(0.0,0.0,1.0f);     
    8.     // 设置光栅化位置,即字体的位置     
    9.     glRasterPos2f(0.0, 0.0);   
    10.     PrintString(listBase,"You are great!");     // 输出文字到屏幕    
    11.     return TRUE;                        // 继续运行  
    12.   
    13. }  

    4.最后在视图源文件的OnDestroy()函数中添加:

          ClearFont(listBase);

    如上使用就没问题了。

    glRasterPos2f(x,y)

     

    glOpenGL 預設的座標系統,
    (1,1) 在視窗的右上方,
    (0,0) 在視窗中心,
    (-1,-1) 在視窗的左下方.

    RasterPos2i()


    glRasterPos2i(200, 200); 改变光栅位置
    光栅(Raster):由像素构成的一个矩形网格。要在光栅上显示的数据保存于帧缓存内。

    1. BOOL COpenglbaseView::RenderScene()  
    2. {  
    3.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         // 清除屏幕及深度缓存     
    4.     glLoadIdentity();    
    5.     glTranslatef(0.0f,0.0f,-10.0f);              // 移入屏幕一个单位     
    6.     // 根据字体位置设置颜色     
    7.     glColor3f(0.0,0.0,1.0f);     
    8.     // 设置光栅化位置,即字体的位置     
    9.     glRasterPos2f(-5, 0.5);   
    10.     PrintString(listBase,"You are great!");     // 输出文字到屏幕    
    11.     return TRUE;                        // 继续运行  
    12.   
    13. }  



    第十一课C:OpenGL显示中文字体

    添加格式控制的又该如何呢?希望继续完善

     OpenglFontInit文件添加中文显示点击打开链接

    1. void PrintCNString(const char* str,HDC hDC)  
    2. {  
    3.     int len, i;  
    4.     wchar_t* wstring;  
    5.     GLuint list = glGenLists(1);  
    6.     // 计算字符的个数  
    7.     // 如果是双字节字符的(比如中文字符),两个字节才算一个字符  
    8.     // 否则一个字节算一个字符  
    9.     len = 0;  
    10.     for(i=0; str[i]!=''; ++i)  
    11.     {  
    12.         if( IsDBCSLeadByte(str[i]) )  
    13.             ++i;  
    14.         ++len;  
    15.     }  
    16.       
    17.     // 将混合字符转化为宽字符  
    18.     wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));  
    19.     MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len);  
    20.     wstring[len] = L'';  
    21.       
    22.     // 逐个输出字符  
    23.     for(i=0; i<len; ++i)  
    24.     {  
    25.         wglUseFontBitmapsW(hDC, wstring[i], 1, list);  
    26.         glCallList(list);  
    27.     }  
    28.       
    29.     // 回收所有临时资源  
    30.     free(wstring);  
    31.     glDeleteLists(list, 1);  
    32.   
    33. }  


     

    显示中文
    原则上,显示中文和显示英文并无不同,同样是把要显示的字符做成显示列表,然后进行调用。
    但是有一个问题,英文字母很少,最多只有几百个,为每个字母创建一个显示列表,没有问题。但是汉字有非常多个,如果每个汉字都产生一个显示列表,这是不切实际的。
    我们不能在初始化时就为每个字符建立一个显示列表,那就只有在每次绘制字符时创建它了。当我们需要绘制一个字符时,创建对应的显示列表,等绘制完毕后,再将它销毁。
    这里还经常涉及到中文乱码的问题,我对这个问题也不甚了解,但是网上流传的版本中,使用了MultiByteToWideChar这个函数的,基本上都没有出现乱码,所以我也准备用这个函数:)
    通常我们在C语言里面使用的字符串,如果中英文混合的话,例如“this is 中文字符.”,则英文字符只占用一个字节,而中文字符则占用两个字节。用MultiByteToWideChar函数,可以转化为所有的字符都占两个字节(同时解决了前面所说的乱码问题:))。
    转化的代码如下:

    // 计算字符的个数
    // 如果是双字节字符的(比如中文字符),两个字节才算一个字符
    // 否则一个字节算一个字符
    len = 0;
    for(i=0; str[i]!=''; ++i)
    {
        if( IsDBCSLeadByte(str[i]) )
            ++i;
        ++len;
    }

    // 
    将混合字符转化为宽字符
    wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len);
    wstring[len] = L'';

    // 
    用完后记得释放内存
    free(wstring);



    加上前面所讲到的wglUseFontBitmaps函数,即可显示中文字符了。

    void drawCNString(const char* str) {
        int len, i;
        wchar_t* wstring;
        HDC hDC = wglGetCurrentDC();
        GLuint list = glGenLists(1);

        // 
    计算字符的个数
        // 如果是双字节字符的(比如中文字符),两个字节才算一个字符
        // 否则一个字节算一个字符
        len = 0;
        for(i=0; str[i]!=''; ++i)
        {
            if( IsDBCSLeadByte(str[i]) )
                ++i;
            ++len;
        }

        // 
    将混合字符转化为宽字符
        wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len);
        wstring[len] = L'';

        // 
    逐个输出字符
        for(i=0; i<len; ++i)
        {
            wglUseFontBitmapsW(hDC, wstring[i], 1, list);
            glCallList(list);
        }

        // 
    回收所有临时资源
        free(wstring);
        glDeleteLists(list, 1);
    }



    注意我用了wglUseFontBitmapsW函数,而不是wglUseFontBitmapswglUseFontBitmapsWwglUseFontBitmaps函数的宽字符版本,它认为字符都占两个字节。因为这里使用了MultiByteToWideChar,每个字符其实是占两个字节的,所以应该用wglUseFontBitmapsW

    void display(void) {
        glClear(GL_COLOR_BUFFER_BIT);

        selectFont(48, ANSI_CHARSET, "Comic Sans MS");
        glColor3f(1.0f, 0.0f, 0.0f);
        glRasterPos2f(-0.7f, 0.4f);
        drawString("Hello, World!");

        selectFont(48, GB2312_CHARSET, "
    楷体_GB2312");
        glColor3f(1.0f, 1.0f, 0.0f);
        glRasterPos2f(-0.7f, -0.1f);
        drawCNString("
    当代的中国汉字");

        selectFont(48, DEFAULT_CHARSET, "
    华文仿宋");
        glColor3f(0.0f, 1.0f, 0.0f);
        glRasterPos2f(-0.7f, -0.6f);
        drawCNString("
    傳統的中國漢字");

        glutSwapBuffers();
    }


    效果如图:
    [转载]opengl文字处理(1) <wbr>(入门学习十六)(转) 

     

    纹理字体
    把文字放到纹理中有很多好处,例如,可以任意修改字符的大小(而不必重新指定字体)。
    对一面飘动的旗帜使用带有文字的纹理,则文字也会随着飘动。这个技术在三国志系列游戏中经常用到,比如关羽的部队,旗帜上就飘着个字,张飞的部队,旗帜上就飘着个字,曹操的大营,旗帜上就飘着个字。三国人物何其多,不可能为每种姓氏都单独制作一面旗帜纹理,如果能够把文字放到纹理上,则可以解决这个问题。(参见后面的例子:绘制一面字旗)
    如何把文字放到纹理中呢?自然的想法就是:如果前面所用的显示列表,可以直接往纹理里面绘制,那就好了。不过,绘制到纹理这种技术要涉及的内容可不少,足够我们专门拿一课的篇幅来讲解了。这里我们不是直接绘制到纹理,而是用简单一点的办法:先把汉字绘制出来,成为像素,然后用glCopyTexImage2D把像素复制为纹理。
    glCopyTexImage2DglTexImage2D的用法是类似的(参见第11课),不过前者是直接把绘制好的像素复制到纹理中,后者是从内存传送数据到纹理中。要使用到的代码大致如下:

    // 先把文字绘制好
    glRasterPos2f(XXX, XXX);
    drawCNString("
    ");
    // 
    分配纹理编号
    glGenTextures(1, &texID);
    // 
    指定为当前纹理
    glBindTexture(GL_TEXTURE_2D, texID);
    // 
    把像素作为纹理数据
    // 将屏幕(0, 0)  (64, 64)的矩形区域的像素复制到纹理中
    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 64, 64, 0);
    // 
    设置纹理参数
    glTexParameteri(GL_TEXTURE_2D,
        GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,
        GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    然后,我们就可以像使用普通的纹理一样来做了。绘制各种物体时,指定合适的纹理坐标即可。
    有一个细节问题需要特别注意。大家看上面的代码,指定文字显示的位置,写的是glRasterPos2f(XXX, XXX);这里来讲讲如何计算这个显示坐标。

    展开全文
  • 重新冻结的位图字体转换器 此命令行程序将简单的自定义位图字体格式转换为AngelCode的 。 还为光栅化TrueType / OpenType字体提供了一些基本支持。 ReFreezed位图字体由两个文件组成:一个图像,其中所有字形都由...
  • 位图字体 它使用位图字体,正如许多基于(EEP)ROM的“ chargen”(字符生成ROM的简称)中所发现的那样。 检查文件夹以获取更多详细信息。
  • 位图字体生成工具

    2018-08-13 20:26:34
    位图字体生成工具 ugui 、 ngui 自定义字体,美术字、、、
  • 位图字体工具BMFont

    2019-04-09 14:11:42
    美工提供的位图字体,经常使用起来比较麻烦,这样就可以用字体工具BMFont,把位图字体做个一个FNT字体来使用啦
  • opengl位图字体

    2015-06-05 22:47:40
    利用opengl技术,使用显示列表,制作位图字体
  • 绘制位图字体

    2012-03-25 08:05:17
    绘制位图字体绘制位图
  • laya 位图字体

    2019-06-20 13:42:23
    我们在使用laya中,或多或少会用到一些位图字体位图字体创建的方式很多,但laya只支持导出为XML的fnt格式,而xml在微信小游戏上需要另加额外的解析库,这就导致了包大小的增加。 而位图字体导出工具并不是只能...

    我们在使用laya中,或多或少会用到一些位图字体,位图字体创建的方式很多,但laya只支持导出为XML的fnt格式,而xml在微信小游戏上需要另加额外的解析库,这就导致了包大小的增加。

    而位图字体导出工具并不是只能导出xml格式的字体,还可以导出成文本格式,既然这样,我们为什么不直接解析文本格式呢?

    下面是我解析文本格式的代码,字体创建是通过http://kvazars.com/littera/ 这个flash字体编辑工具创建,然后导出的时候选择的Text格式。

    我修改了BitmapFont.as代码,在里面加了这几个方法,最主要的是loadFontText方法。

    public function loadFontText(path:String,complete:Handler):void{
    			_path = path;
    			_complete = complete;
    			
    			if (!path || path.indexOf(".fnt") === -1) {
    				console.error('Bitmap font configuration information must be a ".fnt" file');
    				return;
    			}
    			Laya.loader.load([{url: path, type: Loader.TEXT}, {url: path.replace(".fnt", ".png"), type: Loader.IMAGE}], Handler.create(this, _onLoadedText));
    		}
    
    		/**
    		 * @private
    		 */
    		private function _onLoadedText():void {
    			this.parseFontText(Loader.getRes(_path), Loader.getRes(_path.replace(".fnt", ".png")));
    			_complete && _complete.run();
    		}
    
    		public function parseFontText(text:String, texture:Texture):void {
    			if (text == null || texture == null) return;
    			_texture = texture;
    			var tX:int = 0;
    			var tScale:Number = 1;
    			
    			var lines:Array = text.split('\n');
    		
    			if(lines.length<5) return ;
    
    			var tInfo:Object = lineToKV(lines[0]);
    			fontSize = parseInt(tInfo["size"]);
    		
    			var tPadding:String = tInfo["padding"];
    			var tPaddingArray:Array = tPadding.split(',');
    			_padding = [parseInt(tPaddingArray[0]), parseInt(tPaddingArray[1]), parseInt(tPaddingArray[2]), parseInt(tPaddingArray[3])];
    			
    			var count:int = parseInt(lineToKV(lines[3])["count"])+4;
    			var i:int = 4;
    			for (i; i < count; i++) {
    				var tAttribute:Object = lineToKV(lines[i]);
    				var tId:int = parseInt(tAttribute["id"]);
    				
    				var xOffset:Number = parseInt(tAttribute["xoffset"]) / tScale;
    				var yOffset:Number = parseInt(tAttribute["yoffset"]) / tScale;
    				var xAdvance:Number = parseInt(tAttribute["xadvance"]) / tScale;
    				
    				var region:Rectangle = new Rectangle();
    				region.x = parseInt(tAttribute["x"]);
    				region.y = parseInt(tAttribute["y"]);
    				region.width = parseInt(tAttribute["width"]);
    				region.height = parseInt(tAttribute["height"]);
    				
    				var tTexture:Texture = Texture.create((texture as Texture2D), region.x, region.y, region.width, region.height, xOffset, yOffset);
    				_maxWidth = Math.max(_maxWidth, xAdvance + letterSpacing);
    				_fontCharDic[tId] = tTexture;
    				_fontWidthMap[tId] = xAdvance;
    			}
    		}
    		private function lineToKV(line:String):Object{
    			var arr:Array = line.split(' ');
    			var dic:Object = new Object();
    			for(var i:int = 0 ;i<arr.length;++i){
    				var kv:Array = arr[i].split('=');
    				if(kv.length>1 ){
    					dic[kv[0]] = kv[1];
    				}
    			}
    			return dic;
    		}

    使用的时候也很简单,和以前用法差不多

    var bmp:BitmapFont = new BitmapFont();
    bmp.loadFontText("font/font1.fnt",Handler.create(this,function():void{
        Text.registerBitmapFont("myfont",bmp);
    	
        var label:Label = new Label();
        label.font = "myfont";
        babel.text = "test font";
        Laya.stage.addChild(lable);
    }));

     

    展开全文
  • 位图字体工具

    2019-11-26 10:51:30
    Bitmap Font Generator windows软件 在线工具 在线生成位图字体工具
    1. Bitmap Font Generator
      windows软件
    2. 在线工具
      在线生成位图字体工具
    展开全文
  • cocos论坛:位图字体怎么做+- x / 0123456789图片已上传 求指教 cocos教程:艺术数字资源 cocos教程:字体资源 BMFont快速入门教程 一 艺术数字资源 二 BMFont 三 自定义位图字体 四 cocos插件 一 艺术数字资源 艺术...

    版本:2.3.4

    参考:

    cocos论坛:位图字体怎么做+- x / 0123456789图片已上传 求指教

    cocos教程:艺术数字资源

    cocos教程:字体资源

    BMFont快速入门教程

    一 艺术数字资源

    二 BMFont

    三 自定义位图字体

    四 cocos插件

    一 艺术数字资源

    艺术数字资源 是一种用户自定义的资源,它可以用来配置艺术数字字体的属性。

    因为cocos的艺术字体配置,图片中文字需要按照ascii表顺序排列,所以只适合简单的"./0123456789"的位图文字。如果带中文或其他特殊符号,例如"%0123456789成功率",则使用不了了。

    游戏内有使用位图字体,比如打伤害的数字。

    现有字体图片font.png如下

    资源管理器中,选择font文件夹,右键新建艺术字体配置

    创建了一个LabelAtlas文件

     

    选择labelAtlas,将字体图片font.png拖动到Raw Texture File上,并设置字体高宽

    Raw Texture File:字体图片

    Item Width:字体宽度

    Item Height:字体高度

    Start Char:在ascii表的起始字符

    Font Size:字体大小

    拖动LabelAtlas到舞台,并设置string为“0123成功率”,显示的是“%012”

    因为cocos提供的艺术数字配置,必须按照字体表的顺序来使用,Start Char属性就是ascii表起始字符。

    例如Star Char是 .,那么图片必须是./0123456789。例如Start Char是 +,图片就必须是+,-./0123456789的顺序

    图片 “%0123456789成功率“ 必须符合ascii表的顺序,但是这是不可能的,因为还有中文、特殊字符。艺术字体配置这个功能也就成了鸡肋。

    二 BMFont

    BMFont,全称Bitmap font generator,位图文字生成器,能够生成png和fnt两个文件在cocos中使用。

    BMFont下载地址:http://www.angelcode.com/products/bmfont/

     

    BMFont用系统字体生成位图文字在cocos中使用

    打开BMFont,选择Options-Font Setting,选择楷体

    选择Options-Export options,选择Bit depth为32,Texture为png。

    选择+-0123456789

    选择Options-Save bitmap font as

     导出得到两个文件,放到cocos的assets下

    拖拽font到舞台

    设置Label的string为+-123

    效果如图

    除了手选要生成的文字外,还可以通过txt文件自定义需要选中的文字

    新建一个txt文件,要保存为格式UTF-8,内容是"%0123456789成功率"

    选择Edit - Select chars from file

     

     选择Options - Visualize预览,是乱码... 我放弃这个BMFont了

    三 自定义位图字体

    根据Laya的FontClip修改得来自定义组件。

    1. 可以制作成预制件,在自定义控件栏使用。

    2.  没有多行显示。

    新建一个node,添加自定义组件FontClip,并将位图文字拖动到FontClip组件上。

    SpriteFrame:位图文字png

    Sheet:位图对应的字符

    Value:显示的文字

    FontW:单个文字宽度,默认0时根据图片宽度自动计算

    FontH:单个文字高度,默认0时根据图片高度自动计算

    SpaceX:文字间距

    显示效果

    自定义位图文字类FontClip.ts:

    // Learn TypeScript:
    //  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
    // Learn Attribute:
    //  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
    // Learn life-cycle callbacks:
    //  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
    
    import CutImgTool from "../utils/CutImageTool";
    
    const {ccclass, property} = cc._decorator;
    
    /*  Example:
    
        1.使用方式一,代码创建位图字体
        let node:cc.Node = new cc.Node();
        let fontClip = node.addComponent(FontClip);
        fontClip.spaceX = 10;
        fontClip.makeFontSpriteFrame(cc.resource.get("font.png",cc.SpriteFrame) as cc.SpriteFrame,"%0123456789", 26,26);
        fontClip.string = "1234";
        node.x = 0;
        node.y = -100;
        this.node.addChild(node);
        fontClip.node.destroy();
    
        2.使用方式二,Scene中在cc.Node"添加组件"创建
    */
    
    /**
     * 位图字体
     * @author chenkai 2020.8.3
     */
    @ccclass
    export default class FontClip extends cc.Component {
        /**位图文字图片 */
        @property(cc.SpriteFrame)
        spriteFrame:cc.SpriteFrame = null;
        /**位图文字图片对应的字符 */
        @property(cc.String)
        sheet:string = "";
        /**显示字符 */
        @property(cc.String)
        value:string = "";
        /**单个文字宽度 */
        @property(cc.Integer)
        fontW:number = 0;
        /**单个文字高度 */
        @property(cc.Integer)
        fontH:number = 0;
        /**文字水平间距 */
        @property(cc.Integer)
        spaceX:number = 0;
    
    
        /**Sprite缓存 */
        private spriteCaches:Array<cc.Sprite> = [];
        /**SpriteFrame缓存  {key:value} = {char:cc.spriteFrame}*/
        private spriteFrameCaches = {};
        
        
        onLoad(){
            //设置spriteFrame切图
            this.spriteFrame && this.makeFontSpriteFrame(this.spriteFrame,this.sheet, this.fontW, this.fontH);
            //显示默认文字
            if(this.value != ""){
                this.string = this.value;
            }
        }
        
        /**
         * 制作文字的切图
         * @param spriteFrame 文字图片
         * @param sheet       文字图片对应的字符
         * @param fontW       单文字宽度
         * @param fontH       单文字高度
         */
        public makeFontSpriteFrame(spriteFrame:cc.SpriteFrame,sheet:string, fontW:number=0, fontH:number=0){
            this.sheet = sheet;
            //位图文字切图
            let row = 1;
            let col = this.sheet.length;
            let pieceNum = this.sheet.length;
            this.fontW = fontW!=0?fontW:Math.round(spriteFrame.getTexture().width/col);
            this.fontH = fontH!=0?fontH:Math.round(spriteFrame.getTexture().height/row);
            let cutImgs = CutImgTool.cutImg(spriteFrame,row,col,this.fontW,this.fontH,pieceNum);
            //保存文字切片
            for(let key in this.spriteFrameCaches){
                delete this.spriteFrameCaches[key];
            }
            for(let i=0;i<pieceNum;i++){
                this.spriteFrameCaches[this.sheet.charAt(i)] = cutImgs[i];
            }
        }
    
        /**获取一个cc.Sprite */
        private getSprite(){
            if(this.spriteCaches.length > 0){
                return this.spriteCaches.pop();
            }else{
                let node:cc.Node = new cc.Node();
                let sprite:cc.Sprite = node.addComponent(cc.Sprite);
                return sprite;
            }
        }
    
        /**
         * 设置文字
         * @param txt 文字
         */
        public set string(txt:string){
            let curLen = this.node.childrenCount;
            let targetLen = txt.length;
      
            this.value = txt;
      
            //文字存在,且大于显示文字,则移除多余文字
            if(curLen > targetLen){
                let sprite:cc.Sprite;
                for(let i=curLen-1;i>=targetLen;i--){
                    sprite = this.node.children[i].getComponent(cc.Sprite);
                    sprite.node.removeFromParent();
                    sprite.spriteFrame = null;
                    this.spriteCaches.push(sprite);
                }
            }
            //显示文字
            let sprite:cc.Sprite;
            let tempX:number = 0;
            for(let i=0;i<targetLen;i++){
                //少于显示文字,则增加文字
                if(i >= curLen){
                    sprite = this.getSprite();
                    this.node.addChild(sprite.node);
                }
                sprite = this.node.children[i].getComponent(cc.Sprite);
                sprite.spriteFrame =  this.spriteFrameCaches[txt.charAt(i)];
                sprite.node.x = tempX;
                tempX = sprite.node.x +  this.fontW + this.spaceX;
            }
        }
    
        onDestroy(){
            this.spriteFrame = null;
            this.spriteCaches.length = 0;
            for(let key in this.spriteFrameCaches){
                delete this.spriteFrameCaches[key];
            }
        }
    }
    
    

    切图工具类CutImageTool.ts:

    // Learn TypeScript:
    //  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
    // Learn Attribute:
    //  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
    // Learn life-cycle callbacks:
    //  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
    
    
    const {ccclass, property} = cc._decorator;
    
    /**
     * 切图工具
     * @author chenkai 2020.8.3
     */
    export default class CutImgTool{
        /**
         * 切图工具
         * @param spriteFrame   大图
         * @param row           大图中小图行数
         * @param col           大图中小图列数
         * @param width         小图宽
         * @param height        小图高
         * @param pieceNum      小图数量 
         * @param startPos      起始位置,包含该位置,索引从0开始
         * @returns             返回小图数组
         */
        public static cutImg(spriteFrame:cc.SpriteFrame,row:number,col:number, width:number, height:number, pieceNum:number,startPos:number=0){
            let texture = spriteFrame.getTexture();
            let size = spriteFrame.getOriginalSize();
            let sum:number = 0;
            let arr:Array<cc.SpriteFrame> = [];
            for(let i=0;i<row;i++){
                for(let j=0;j<col;j++){
                    if(i*col+j>=startPos){
                        if(j*width+width > size.width || i*height+height>size.height){
                            console.error("CutImgTool >> 切图超出大图范围,大图xMax,yMax:", size.width,size.height,"切图范围xMax,yMax:",j*width+width,i*height+height);
                            return arr;
                        }
                        let newSp = new cc.SpriteFrame(texture, cc.rect(0,0,texture.width,texture.height));
                        newSp.setRect(cc.rect(j*width,i*height,width,height));
                        arr.push(newSp);
                        sum++;
                        if(sum >= pieceNum){
                            return arr;
                        }
                    }
                }
            }
            return arr;
        }
    
      
    }
    
    

     四 cocos插件

    cocos商店中买12大洋的插件

    插件的功能就是将文字碎图,到处为cocos可以直接使用的fnt和png文件。同时还支持ttf字体制作位图字体。

    插件使用界面

     

    这个插件相对于BMFont那蹩脚的界面,已经改良很多了。

    展开全文
  • monomacs:程序员的位图字体
  • bitmapfonts:位图字体API和工具
  • 樱桃:另一种位图字体
  • Phaser Arial位图字体 Phaser 2和3的Arial位图字体。 通过使用以下方式获得:
  • Bitmap2ttf将(单色)位图字体转换为ttf字体。 分为三个部分: outliner.py: 将每个位图跟踪到一系列多边形中。 convert.py: 将多边形制作为svg文件,并编写脚本以进行字体伪造,以将svgs转换为ttf字体。 您...
  • Laya的位图字体bitmapFont字体用法

    千次阅读 2019-03-17 15:59:42
    &nbsp; 一 效果 &nbsp; 二 工具 BMFont (下载地址:http://www.angelcode.com/products/bmfont/) ...建议下载第三个,不需要安装,双击打开直接使用 ...四 制作位图字体 选择Edit -&gt; Ope...
  • 位图字体导入器 是完美的Unity资源插件,可将任何自定义位图字体导入到您的项目中。 它可以轻松导入由第三方工具生成的任何位图字体,例如: , , , 或 Thiks @Xylph,这个起源代码的形式 特征 自由 自动导入...
  • fontbuilder, 位图字体生成器 另一个位图字体生成器。使用 FreeType,TrueType和一些其它字体格式的位图字符创建纹理地图集的工具。当前状态:alpha下载:来自github的支持: gamedev.ru 论坛主题( 俄罗斯)与其他...
  • 很好用的位图字体编辑工具littera,可以导出.fnt/.txt文件
  • xsg-fonts:终端仿真器位图字体
  • Gohufont是一种等宽位图字体,高度为11像素和14像素。 网站 有关更多信息和屏幕截图,请访问网站 执照 Hugo Chargois版权所有2015 该字体是根据的条款发布的(请参阅COPYING-LICENSE)。 致谢与致谢 11像素字体的...
  • 使用TextureMerger制作位图字体,具体查看官方教程。 我们这里制作了一组位图字体。 二、导入位图字体 位图字体素材放入资源配置文件default.res.json 三、EXML中使用位图字体 拖动一个bitmaplabel组件...
  • Laya位图字体制作

    2019-05-05 12:52:38
    在开发中会依据美术的需求使用特殊的字体来实现游戏的整体风格,...1.下载windows免费的位图字体制作工具Bitmap Font Generator 下载地址:http://www.angelcode.com/products/bmfont/ 2.打开软件,选择 Edit->...
  • Nixedsys 是一种 8x15 像素的主要无衬线等宽位图字体。 它作为 TrueType 字体 Fixedsys Excelsior 的位图替代品存在。 安装 将字体复制或符号链接到您的 ~/.fonts 目录: cp nixedsys-normal.bdf ~/.fonts 运行fc-...
  • SnowBamboo位图字体生成器在线 最近,, 。 这也意味着我们以前经常使用的在线工具Littera在Chrome中不再可用。 SnowBamboo应用了Canvas API并遵循现代浏览器的规范,使在线编辑位图字体变得简单。 它计划与Littera...
  • 脾脏是等宽的位图字体,有6种尺寸可用: 5x8 6x12 8x16 12x24 16x32 32x64 每种大小均以字形位图分布格式(BDF)提供,发行版tarball包含以下格式的字体: PCF , PSF (对于Linux控制台)和OTF 。 所有字体...
  • 用于在所有openfl目标上使用位图字体呈现文本的组件。 这组类主要基于从pixelizer(类从约翰的Peitz)(johanpeitz.com)和BitmapText类从HaxePunk( ) 它支持AngelCode,XNA和等宽位图字体。 此组件中的文本...
  • 该应用程序旨在成为一种简单但已经有用的工具,用于设计位图字体。 可能还有其他工具可用于此目的,但是此工具尤其允许生成Qt资源文件以及各个资源。 这些资源包括一个清单XML文件(描述每个位图字体)和多个带有...
  • neodgm:现代的TrueType字体,基于旧的但很好的韩国位图字体
  • 前言由于有开发者反馈位图字体不会用,上周对位图字体的官网文档进行了更新,把细节介绍的更清晰了。今天,又遇到有没看文档的开发者来提问位图字体的使用问题,因此将官网文档同步到公众号,让更多人...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,114
精华内容 845
关键字:

位图字体