青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

  C++博客 :: 首頁 :: 聯系 ::  :: 管理
  163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

常用鏈接

留言簿(48)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 402531
  • 排名 - 59

最新評論

閱讀排行榜

評論排行榜

這節課繼續上一節課課的內容。在第13課我們學習了如何使用位圖字體,這節課,我們將學習如何使用輪廓字體。
創建輪廓字體的方法類似于在第13課中我們創建位圖字體的方法。但是,輪廓字體看起來要酷100倍!你可以指定輪廓字體的大小。輪廓字體可以在屏幕中以3D方式運動,而且輪廓字體還可以有一定的厚度!而不是平面的2D字符。使用輪廓字體,你可以將你的計算機中的任何字體轉換為OpenGL中的3D字體,加上合適的法線,在有光照的時候,字符就會被很好的照亮了。

一個小注釋,這段代碼是專門針對Windows寫的,它使用了Windows的wgl函數來創建字體,顯然,Apple機系統有agl,X系統有glx來支持做同樣事情的,不幸的是,我不能保證這些代碼也是容易使用的。如果哪位有能在屏幕上顯示文字且獨立于平臺的代碼,請告訴我,我將重寫一個有關字體的教程。

我們從第一課的典型代碼開始,添加上stdio.h頭文件以便進行標準輸入/輸出操作,另外,stdarg.h頭文件用來解析文字以及把變量轉換為文字。最后加上math.h頭文件,這樣我們就可以使用SIN和COS函數在屏幕中移動文字了。
 
  
  
 另外,我們還要添加2個變量。base將保存我們創建的第一個顯示列表的編號。每個字符都需要有自己的顯示列表。例如,字符‘A’在顯示列表中是65,‘B’是66,‘C’是67,等等。所以,字符‘A’應保存在顯示列表中的base + 65這個位置。
我們再添加一個叫做rot的變量。用它配合SIN和COS函數在屏幕上旋轉文字。我們同時用它來改變文字的顏色。

 
  

GLuint    base;            // 繪制字體的顯示列表的開始位置
GLfloat    rot;            // 旋轉字體

  
 GLYPHMETRICSFLOAT gmf[256]用來保存256個輪廓字體顯示列表中對應的每一個列表的位置和方向的信息。我們通過gmf[num]來選擇字母。num就是我們想要了解的顯示列表的編號。在稍后的代碼中,我將說明如何如何檢查每個字符的寬度,以便自動將文字定位在屏幕中心。切記,每個字符的寬度可以不相同。Glyphmetrics會大大簡化我們的工作。 
  

GLYPHMETRICSFLOAT gmf[256];    // 記錄256個字符的信息

  
 下面這段用來構建真正的字體的代碼類似于我們創建位圖字體的方法。和13課一樣,只是使用wglUseFontOutlines函數替換wglUseFontBitmaps函數。
 
  

base = glGenLists(256);                        // 創建256個顯示列表   
wglUseFontOutlines(    hDC,                    // 設置當前窗口設備描述表的句柄
                0,                // 用于創建顯示列表字體的第一個字符的ASCII值
                255,                // 字符數
                base,                // 第一個顯示列表的名稱

  
 That's not all however. We then set the deviation level. The closer to 0.0f, the smooth the font will look. After we set the deviation, we get to set the font thickness. This describes how thick the font is on the Z axis. 0.0f will produce a flat 2D looking font and 1.0f will produce a font with some depth.

The parameter WGL_FONT_POLYGONS tells OpenGL to create a solid font using polygons. If we use WGL_FONT_LINES instead, the font will be wireframe (made of lines). It's also important to note that if you use GL_FONT_LINES, normals will not be generated so lighting will not work properly.

The last parameter gmf points to the address buffer for the display list data.  
  

                0.0f,                // 字體的光滑度,越小越光滑,0.0為最光滑的狀態
                0.2f,                // 在z方向突出的距離
                WGL_FONT_POLYGONS,            // 使用多邊形來生成字符,每個頂點具有獨立的法線
                gmf);                //一個接收字形度量數據的數組的地址,每個數組元素用它對應的顯示列表字符的數據填充
}

  
 The following code is pretty simple. It deletes the 256 display lists from memory starting at the first list specified by base. I'm not sure if Windows would do this for you, but it's better to be safe than sorry :)  
  

GLvoid KillFont(GLvoid)                        // 刪除顯示列表
{
     glDeleteLists(base, 256);                    // 刪除256個顯示列表
}

  
 下面就是我優異的GL文字程序了。你可以通過調用glPrint(“需要寫的文字”)來調用這段代碼。文字被存儲在字符串text[]中。 
  

GLvoid glPrint(const char *fmt, ...)                    // 自定義GL輸出字體函數
{

  
 下面的第一行定義了一個叫做length的變量。我們使用這個變量來查詢字符串的長度。第二行創建了一個大小為256個字符的字符數組,里面保存我們想要的文字串。第三行創建了一個指向一個變量列表的指針,我們在傳遞字符串的同時也傳遞了這個變量列表。如果我們傳遞文字時也傳遞了變量,這個指針將指向它們。 
  

    float        length=0;                    // 查詢字符串的長度
    char        text[256];                // 保存我們想要的文字串
    va_list        ap;                    // 指向一個變量列表的指針

  
 下面兩行代碼檢查是否有需要顯示的內容,如果什么也沒有,屏幕上也就什么都沒有。
 
  

    if (fmt == NULL)                        // 如果無輸入則返回
        return;                   
  
 接下來三行代碼將文字中的所有符號轉換為它們的字符編號。最后,文字和轉換的符號被存儲在一個叫做“text”的字符串中。以后我會多解釋一些有關字符的細節。 
  

    va_start(ap, fmt);                        // 分析可變參數
        vsprintf(text, fmt, ap);                // 把參數值寫入字符串
    va_end(ap);                        // 結束分析

  
 感謝Jim Williams對下面一段代碼的建議。以前我是用手工將文字置于中心的,而他的辦法要好的多。
我們從一個循環開始,它將逐個檢查文本中的字符。我們通過strlen(text)得到文本的長度。設置好了循環以后,我們將通過加上每個字符的長度來增加length的值。當循環結束以后,被保存在length中的值就是整個字符串的長度。所以,如果我們要寫的是“hello”,假設每個字符的長度都為10個單位,我們先給length的值加上第一個字母的長度10。然后,我們檢查第二個字母的長度,它的長度也是10,所以length就變成10 + 10(20)。當我們檢查完所有5個字母以后,length的值就會等于50(5 *10)。

給出我們每個字符的長度的代碼是gmf[text[loop]].gmfCellIncX。記住,gmf存儲了我們每個顯示列表的信息。如果loop等于0,text[loop]就是我們的字符串中的第一個字符。如果loop等于1,text[loop]就是我們的字符串中的第二個字符。gmfCellIncX告訴我們被選擇的字符的長度。GmfCellIncX表示顯示位置從已繪制上的上一個字符向右移動的真正距離,這樣,字符之間就不會重疊在一起。同時,這個距離就是我們想得到的字符的寬度。你還可以通過gmfCelllncY命令來得到字符的高度。如果你是在垂直方向繪制文本而不是在水平方向時,這會很方便。

 
  

    for (unsigned int loop=0;loop<(strlen(text));loop++)    // 查找整個字符串的長度
    {
        length+=gmf[text[loop]].gmfCellIncX;       
    }

  
 最后我們取出計算后得到的length,并把它變成負數(因為我們要將文本從屏幕中心左移從而把整個文本置于屏幕中間)。然后我們把length除以2。我們并不想移動整個文本的長度,只需要一半! 
  

    glTranslatef(-length/2,0.0f,0.0f);            // 把字符串置于最左邊

  
 然后我們將GL_LIST_BIT壓入屬性堆棧,它會防止glListBase影響到我們的程序中的其它顯示列表 
  

    glPushAttrib(GL_LIST_BIT);                // 把顯示列表屬性壓入屬性堆棧
    glListBase(base);                    // 設置顯示列表的基礎值為0

  
 現在OpenGL知道字符的存放位置了,我們就可以讓它在屏幕上顯示文字了。GlCallLists會調用多個顯示列表從而把整個文字的內容同時顯示在屏幕上。
下面的代碼做后續工作。首先,它告訴OpenGL我們將要在屏幕上顯示出顯示列表中的內容。Strlen(text)函數用來計算我們將要顯示在屏幕上的文字的長度。然后,OpenGL需要知道我們允許發送給它的列表的最大值。我們依然不能發送長度大于255的字符串。所以我們使用UNSIGNED_BYTE。(用0 - 255來表示我們需要的字符)。最后,我們通過傳遞字符串文字告訴OpenGL顯示什么內容。

也許你想知道為什么字符不會彼此重疊堆積在一起。那時因為每個字符的顯示列表都知道字符的右邊緣在那里,在寫完一個字符后,OpenGL自動移動到剛寫過的字符的右邊,在寫下一個字或畫下一個物體時就會從GL移動到的最后的位置開始,也就是最后一個字符的右邊。

最后,我們將GL_LIST_BIT屬性彈出堆棧,將GL恢復到我們使用glListBase(base)設置base之前的狀態。

 
  

    glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);    // 調用顯示列表繪制字符串
    glPopAttrib();                    // 彈出屬性堆棧
}
  
 下面就是畫圖的代碼了。我們從清除屏幕和深度緩存開始。我們調用glLoadIdentity()來重置所有東西。然后我們將坐標系向屏幕里移動十個單位。輪廓字體在透視圖模式下表現非常好。你將文字移入屏幕越深,文字開起來就更小。文字離你越近,它看起來就更大。
也可以使用glScalef(x,y,z)命令來操作輪廓字體。如果你想把字體放大兩倍,可以使用glScalef(1.0f,2.0f,1.0f). 2.0f 作用在y軸, 它告訴OpenGL將顯示列表的高度繪制為原來的兩倍。如果2.0f作用在x軸,那么文本的寬度將變成原來的兩倍。

 
  

int DrawGLScene(GLvoid)                    // 此過程中包括所有的繪制代碼
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 清除屏幕及深度緩存
    glLoadIdentity();                    // 重置當前的模型觀察矩陣
    glTranslatef(0.0f,0.0f,-10.0f);            // 移入屏幕一個單位

  
 在向屏幕里移動以后,我們希望文本能旋轉起來。下面3行代碼用來在3個軸上旋轉屏幕。我將rot乘以不同的數,以便每個方向上的旋轉速度不同。 
  

    glRotatef(rot,1.0f,0.0f,0.0f);            // 沿X軸旋轉
    glRotatef(rot*1.5f,0.0f,1.0f,0.0f);            // 沿Y軸旋轉
    glRotatef(rot*1.4f,0.0f,0.0f,1.0f);            // 沿Z軸旋轉

  
 下面是令人興奮的顏色循環了。照常,我們使用唯一遞增的變量(rot)。顏色通過使用COS和SIN來循環變化。我將rot除以不同的數,這樣每種顏色會以不同的速度遞增。最終的效果非常好。
 
  

    // 根據字體位置設置顏色
    glColor3f(1.0f*float(cos(rot/20.0f)),1.0f*float(sin(rot/25.0f)),1.0f-0.5f*float(cos(rot/17.0f)));

  
 我最喜歡的部分,將文字寫到屏幕上。我使用同將位圖字體寫到屏幕上相同的函數。將文字寫在屏幕上,所有你要做的就是glPrint(“你想寫的文字”)。很簡單。
在下面的代碼中,我們要寫的是NeHe,空格,破折號,空格,然后是rot的值除以50后的結果(為了減慢計數器)。如果這個數大于999.99,左邊第四個數將被去掉(我們要求只顯示小數點左邊3位數字)。只顯示小數點右邊的兩位數字。
 
  

     glPrint("NeHe - %3.2f",rot/50);                // 輸出文字到屏幕

  
 然后增大旋轉變量從而改變顏色并旋轉文字。 
  
posted on 2007-12-14 14:27 sdfasdf 閱讀(291) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品国产三级欧美二区| 久久精品伊人| 国产有码一区二区| 国产嫩草影院久久久久| 国产精品亚洲综合久久| 国产欧美一区二区三区在线老狼| 国产丝袜一区二区三区| 尤物精品国产第一福利三区| 亚洲电影免费观看高清完整版| 亚洲黄色成人久久久| 一区二区国产日产| 亚洲欧美色婷婷| 狂野欧美激情性xxxx| 久久久蜜臀国产一区二区| 久久综合激情| 亚洲美女毛片| 欧美一区二区性| 亚洲在线网站| 国产精品xvideos88| 国产亚洲一级| 99国内精品| 久久久久久久久综合| 亚洲第一页中文字幕| 亚洲风情在线资源站| 亚洲欧美日本伦理| 欧美电影在线观看| 国产日韩欧美中文| 一本色道久久综合亚洲91| 久色婷婷小香蕉久久| 欧美电影免费网站| 亚洲天堂av在线免费| 免费成人av在线看| 久久亚洲综合| 亚洲一区二区动漫| 欧美国产日本韩| 欧美在线观看一区| 欧美色精品在线视频| 在线国产日韩| 久久国产直播| 一区二区久久久久| 欧美电影免费网站| 1024亚洲| 久久亚洲视频| 欧美一区二区视频在线| 国产精品久久久久久久久动漫| 麻豆成人小视频| 亚洲调教视频在线观看| 欧美国产日韩亚洲一区| 原创国产精品91| 久久久7777| 欧美亚洲自偷自偷| 国产女主播视频一区二区| 在线亚洲成人| 亚洲免费观看| 午夜精品福利电影| 中文国产一区| 99成人在线| 欧美日韩中文| 亚洲一区二区免费在线| 99re6热在线精品视频播放速度| 免费看成人av| 亚洲三级影片| 亚洲欧洲在线看| 欧美激情国产高清| 亚洲国产欧美在线人成| 亚洲成人在线免费| 午夜国产精品影院在线观看| 国产精品黄视频| 久久aⅴ国产欧美74aaa| 国产欧美一级| 久久综合狠狠综合久久激情| 久久久久国产精品麻豆ai换脸| 国产欧美日本| 美女视频黄免费的久久| 亚洲国产清纯| 国产精品久久久久久模特| 亚洲性夜色噜噜噜7777| 含羞草久久爱69一区| 国内精品伊人久久久久av影院| 久久久久久久久久久久久女国产乱| 亚洲欧美综合另类中字| 国产精品久久久久久久午夜| 久久久久久999| 亚洲二区三区四区| 欧美激情一区二区三区在线视频| 免费欧美在线视频| 99这里有精品| 亚洲女同精品视频| 韩国成人理伦片免费播放| 欧美成人小视频| 欧美网站在线观看| 久久精品一区二区三区四区 | 亚洲在线观看视频| 亚洲在线日韩| 久久久噜噜噜久久久| 中国日韩欧美久久久久久久久| 午夜精品视频在线观看| 91久久精品www人人做人人爽| 一区二区三区精品视频在线观看| 国内精品伊人久久久久av影院| 亚洲国内欧美| 国产精品免费看片| 欧美aⅴ一区二区三区视频| 亚洲精品乱码久久久久久黑人| 蜜桃av一区二区三区| 欧美日韩国产免费观看| 久久精品在线| 久久久久久国产精品一区| 亚洲伊人伊色伊影伊综合网| 久久丁香综合五月国产三级网站| 亚洲美女视频在线观看| 午夜一区二区三区不卡视频| 亚洲美女福利视频网站| 欧美一区二区视频观看视频| 国产精品xnxxcom| 91久久精品视频| 韩国福利一区| 亚洲自拍啪啪| 在线视频欧美日韩精品| 免费在线播放第一区高清av| 久久久91精品国产一区二区三区 | 国产欧美午夜| 亚洲视频在线播放| 日韩视频免费看| 牛牛精品成人免费视频| 久久综合九色| 国产一二精品视频| 国内精品伊人久久久久av一坑| 久久久国产一区二区| 国产精品久久久爽爽爽麻豆色哟哟| 亚洲国内高清视频| 亚洲人成在线影院| 蜜臀va亚洲va欧美va天堂| 老牛国产精品一区的观看方式| 国产嫩草一区二区三区在线观看| 亚洲小说欧美另类婷婷| 亚洲欧美色一区| 六月婷婷一区| 亚洲欧美日韩国产综合| 亚洲欧洲av一区二区| 蜜臀久久99精品久久久画质超高清| 玖玖玖国产精品| 亚洲激情成人在线| 亚洲欧美日本国产有色| 欧美高清日韩| 久久国产精品72免费观看| 欧美日韩综合在线免费观看| 亚洲精品免费在线播放| 暖暖成人免费视频| 久久精品2019中文字幕| 国产一二精品视频| 久久精品成人一区二区三区| 亚洲欧美视频一区二区三区| 国产精品嫩草99a| 欧美一级久久久| 亚洲在线免费| 狠久久av成人天堂| 美女在线一区二区| 欧美中文在线字幕| 激情婷婷亚洲| 亚洲电影免费在线观看| 欧美国产大片| 欧美一区二区三区四区在线观看| 午夜精品电影| 激情文学综合丁香| 亚洲国产精品久久久久| 欧美日韩国产探花| 久久精品一区二区三区四区| 欧美大片在线看免费观看| 欧美日本一区二区视频在线观看| 国际精品欧美精品| 欧美高清成人| 最新国产拍偷乱拍精品 | 久久9热精品视频| 欧美三日本三级三级在线播放| 国产精品看片你懂得| 曰韩精品一区二区| 亚洲欧美国产制服动漫| 国产精品久久久久免费a∨| 国产欧亚日韩视频| 樱桃成人精品视频在线播放| 香蕉久久夜色精品国产| 欧美激情a∨在线视频播放| 亚洲欧美国产高清| 欧美日韩日本国产亚洲在线| 国产欧美日韩在线| 在线精品福利| 欧美成人精品在线| 欧美亚洲一区在线| 国产乱码精品一区二区三区不卡 | 一区二区三区在线不卡| 欧美成人一区二区在线| 欧美3dxxxxhd| 久久先锋影音| 乱码第一页成人| 国产精品一区视频| 午夜日韩电影| 亚洲精品免费观看| 老司机一区二区| 欧美国产日韩视频|