• <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>

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

            常用鏈接

            留言簿(48)

            我參與的團隊

            搜索

            •  

            積分與排名

            • 積分 - 398977
            • 排名 - 59

            最新評論

            閱讀排行榜

            評論排行榜

            在發布了前兩篇關于位圖字體和輪廓字體的教程以后,我收到很多郵件,很多讀者都想知道如何才能給字體賦予紋理貼圖。你可以使用自動紋理坐標生成器。它會為字體上的每一個多邊形生成紋理坐標。
            一個小注釋,這段代碼是專門針對Windows寫的,它使用了Windows的wgl函數來創建字體,顯然,Apple機系統有agl,X系統有glx來支持做同樣事情的,不幸的是,我不能保證這些代碼也是容易使用的。如果哪位有能在屏幕上顯示文字且獨立于平臺的代碼,請告訴我,我將重寫一個有關字體的教程。

            我們將使用第14課的代碼來創作紋理字體的演示。如果程序中哪部分的代碼有變化,我會重寫那部分的所有代碼以便看出我做的改動。

             
              
              
             我們還要添加一個叫做texture[]的整型變量。它用于保存紋理。后面3行是第14課中的代碼,本課不做改動。
             
              
              
             下面的部分做了一些小改動。我打算在這課使用wingdings字體來顯示一個海盜旗(骷髏頭和十字骨頭)的標志。如果你想顯示文字的話,就不用改動第14課中的代碼了,也可以選擇另一種字體。
            有些人想知道如何使用wingdings字體,這也是我不用標準字體的一個原因。wingdings是一種符號字體,使用它時需要做一些改動。告訴Windows使用wingdings字體并不太簡單。如果你把字體的名字改為wingdings,你會注意到字體其實并沒有選到。你必須告訴Windows這種字體是一種符號字體而不是一種標準字符字體。后面會繼續解釋。

             
              

            GLvoid BuildFont(GLvoid)                        // 創建位圖字體
            {
                GLYPHMETRICSFLOAT    gmf[256];                    // 記錄256個字符的信息
                HFONT    font;                        // 字體句柄

                base = glGenLists(256);                    // 創建256個顯示列表
                font = CreateFont(    -12,                    // 字體高度
                            0,                // 字體寬度
                            0,                // 字體的旋轉角度 Angle Of Escapement
                            0,                // 字體底線的旋轉角度Orientation Angle
                            FW_BOLD,                // 字體的重量
                            FALSE,                // 是否使用斜體
                            FALSE,                // 是否使用下劃線
                            FALSE,                // 是否使用刪除線

              
             這就是有魔力的那一行!不使用第14課中的ANSI_CHARSET,我們將使用SYMBOL_CHARSET。這會告訴Windows我們創建的字體并不是由標準字符組成的典型字體。所謂符號字體通常是由一些小圖片(符號)組成的。如果你忘了改變這行,wingdings,webdings以及你想用的其它符號字體就不會工作。
             
              

                            SYMBOL_CHARSET,            // 設置字符集

              
             下面幾行沒有變化。
             
              

                            OUT_TT_PRECIS,            // 輸出精度
                            CLIP_DEFAULT_PRECIS,        // 裁剪精度
                            ANTIALIASED_QUALITY,        // 輸出質量
                            FF_DONTCARE|DEFAULT_PITCH,        // Family And Pitch

              
             既然我們已經選擇了符號字符集標識符,我們就可以選擇wingdings字體了 
              

                            "Wingdings");            // 字體名稱

              
             剩下幾行代碼沒有變化 
              

                SelectObject(hDC, font);                    // 選擇創建的字體

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

              
             我們允許有更多的誤差,這意味著GL不會嚴格的遵守字體的輪廓線。如果你把誤差設置為0.0f,你就會發現嚴格地在曲面上貼圖存在一些問題。但是如果你允許一定的誤差,很多問題都可以避免。
             
              

                            0.1f,                // 字體的光滑度,越小越光滑,0.0為最光滑的狀態

              
             下面三行代碼還是相同的 
              

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

              
             在ReSizeGLScene()函數之前,我們要加上下面一段代碼來讀取紋理。你可能會認得這些前幾課中的代碼。我們創建一個保存位圖的地方,讀取位圖,告訴Windows生成一個紋理,并把它保存在texture[0]中。
            我們創建一種細化紋理(mipmapped texture),這樣會看起來好些。紋理的名字叫做lights.bmp。
             
              

            if (TextureImage[0]=LoadBMP("Data/Lights.bmp"))            // 載入位圖

              
             下面四行代碼將為我們繪制在屏幕上的任何物體自動生成紋理坐標。函數glTexGen非常強大,而且復雜,如果要完全講清楚它的數學原理需要再寫一篇教程。不過,你只要知道GL_S和GL_T是紋理坐標就可以了。默認狀態下,它被設置為提取物體此刻在屏幕上的x坐標和y坐標,并把它們轉換為頂點坐標。你會發現到物體在z平面沒有紋理,只顯示一些斑紋。正面和反面都被賦予了紋理,這些都是由glTexGen函數產生的。(X(GL_S)用于從左到右映射紋理,Y(GL_T)用于從上到下映射紋理。
            GL_TEXTURE_GEN_MODE允許我們選擇我們想在S和T紋理坐標上使用的紋理映射模式。你有3種選擇:

            GL_EYE_LINEAR - 紋理會固定在屏幕上。它永遠不會移動。物體將被賦予處于它通過的地區的那一塊紋理。

            GL_OBJECT_LINEAR - 這種就是我們使用的模式。紋理被固定于在屏幕上運動的物體上。
            GL_SPHERE_MAP - 每個人都喜歡。創建一種有金屬質感的物體。

             
              

                    // 設置紋理映射模式
                    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
                    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
                    glEnable(GL_TEXTURE_GEN_S);                // 使用自動生成紋理
                    glEnable(GL_TEXTURE_GEN_T);       
              
             在InitGL()的最后有幾行新代碼。BuildFont()被放到了讀取紋理的代碼之后。glEnable(GL_COLOR_MATERIAL) 這行被刪掉了,如果你想使用glColor3f(r,g,b)來改變紋理的顏色,那么就把glEnable(GL_COLOR_MATERIAL)這行重新加到這部分代碼中。 
              

            int InitGL(GLvoid)                            // 此處開始對OpenGL進行所有設置
            {
                if (!LoadGLTextures())                    // 載入紋理
                {
                    return FALSE;                    // 失敗則返回
                }
                BuildFont();                        // 創建字體顯示列表

                glShadeModel(GL_SMOOTH);                    // 啟用陰影平滑
                glClearColor(0.0f, 0.0f, 0.0f, 0.5f);            // 黑色背景
                glClearDepth(1.0f);                    // 設置深度緩存
                glEnable(GL_DEPTH_TEST);                    // 啟用深度測試
                glDepthFunc(GL_LEQUAL);                    // 所作深度測試的類型
                glEnable(GL_LIGHT0);                    // 使用第0號燈
                glEnable(GL_LIGHTING);                    // 使用光照
                glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);        // 告訴系統對透視進行修正

              
             啟動2D紋理映射,并選擇第一個紋理。這樣就把第一個紋理映射到我們繪制在屏幕上的3D物體上了。如果你想加入更多的操作,可以按自己的意愿啟動或禁用紋理映射。 
              

                glEnable(GL_TEXTURE_2D);                    // 使用二維紋理
                glBindTexture(GL_TEXTURE_2D, texture[0]);            // 選擇使用的紋理
                return TRUE;                        // 初始化成功
            }

              
             重置大小的代碼沒有變化,但DrawGLScene這部分代碼有變化。 
              
              
             這里是第一處變動。我們打算使用COS和SIN讓物體繞著屏幕旋轉而不是把它固定在屏幕中間。我們將把物體向屏幕里移動3個單位。在x軸,我們將移動范圍限制在-1.1到+1.1之間。我們使用rot變量來控制左右移動。我們把上下移動的范圍限制在+0.8到-0.8之間。同樣使用rot變量來控制上下移動(最好充分利用你的變量)。 
              

                // 設置字體的位置
                glTranslatef(1.1f*float(cos(rot/16.0f)),0.8f*float(sin(rot/20.0f)),-3.0f);

              
             下面做常規的旋轉。這會使符號在X,Y和Z軸旋轉。 
              

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

              
             我們將物體相對觀察點向左向下移動一點,以便于把符號定位于每個軸的中心。否則,當我們旋轉它的時候,看起來就不像是在圍繞它自己的中心在旋轉。-0.35只是一個能讓符號正確顯示的數。我也試過一些其它數,因為我不知道這種字體的寬度是多少,可以適情況作出調整。我不知道為什么這種字體沒有一個中心。 
              

                glTranslatef(-0.35f,-0.35f,0.1f);                // 移動到可以顯示的位置

              
             最后,我們繪制海盜旗的符號,然后增加rot變量,從而使這個符號在屏幕中旋轉和移動。如果你不知道我是如何從字母‘N’中得到海盜旗符號的,那就打開Microsoft Word或是寫字板。在字體下拉菜單中選擇Wingdings字體。輸入大寫字母‘N’,就會顯示出海盜旗符號了。 
              

                glPrint("N");                        // 繪制海盜旗符號
                rot+=0.1f;                        // 增加旋轉變量

              
             最后要做的事就是在KillGLWindow()的最后添加KillFont()函數,如下所示。添加這行代碼很重要。它將在我們退出程序之前做清理工作。
             
              
              
             盡管我沒有講的細致入微,但我想你應該很好的理解了如何讓OpenGL為你生成紋理坐標。在給你的字體或者是同類物體賦予紋理映射時,應該沒有問題了,而且只需要改變兩行代碼,你就可以啟用球體映射了,它的效果簡直酷斃了!

             


            posted on 2007-12-14 14:30 sdfasdf 閱讀(663) 評論(0)  編輯 收藏 引用 所屬分類: OPENGL
            国产精品青草久久久久婷婷| 四虎亚洲国产成人久久精品| 伊人久久免费视频| 污污内射久久一区二区欧美日韩| 国内高清久久久久久| 99久久亚洲综合精品成人| 久久经典免费视频| Xx性欧美肥妇精品久久久久久| 久久大香萑太香蕉av| 91久久精品视频| 国内精品久久人妻互换| 无码乱码观看精品久久| 91精品国产91久久久久久蜜臀| 99久久无色码中文字幕人妻 | 久久人人爽人人爽人人片AV不| 99久久国产免费福利| 国内精品久久久久伊人av| 中文字幕精品无码久久久久久3D日动漫 | 国产精品九九九久久九九| 欧美精品乱码99久久蜜桃| 国产精品成人精品久久久| 精品久久8x国产免费观看| 97久久国产露脸精品国产| 伊人久久精品影院| 久久久久久av无码免费看大片| 情人伊人久久综合亚洲| 久久电影网一区| 国产精品久久久久…| 久久久久久国产精品无码超碰| 久久久久青草线蕉综合超碰 | 青青热久久综合网伊人| 97久久久精品综合88久久| 久久国产亚洲精品无码| 麻豆成人久久精品二区三区免费| 久久精品一本到99热免费| 久久久久久亚洲精品影院| 亚洲第一永久AV网站久久精品男人的天堂AV | 精品久久综合1区2区3区激情| 久久精品国产69国产精品亚洲| 99久久国产综合精品麻豆| 久久国产免费观看精品|