• <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++博客 :: 首頁 :: 聯(lián)系 ::  :: 管理
              163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(48)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            積分與排名

            • 積分 - 399102
            • 排名 - 59

            最新評論

            閱讀排行榜

            評論排行榜

             歡迎來到NeHe教程第38課。離上節(jié)課的寫作已經(jīng)有些時日了,加上寫了一整天的code,也許筆頭已經(jīng)開始生銹了 :)
            現(xiàn)在你已經(jīng)學(xué)會了如何做方格貼圖,如何讀入bitmap及各種光柵圖像...那么如何做三角形貼圖,又如何在.exe文件中體現(xiàn)你的紋理呢?

            我每每被問及這兩個問題,可是一旦你看到他們是多么簡單,你就會大罵自己居然沒有想到過 :)

            我不會事無巨細(xì)地解釋每一個細(xì)節(jié),只需給你一些抓圖,就明白了。我將基于最新的code,請在主頁"NeHeGL I Basecode"下或者這張網(wǎng)頁最下面下載。

            首先,我們把圖像加載入資源文件。我向大家已經(jīng)知道怎么做了,只是,你忽略了幾步,于是值得到一些無用的資源文件。里面有bitmap文件,卻無法使用。

            還記得吧?我們使用Visual C++ 6.0 做的。如果你使用其它工具,這頁教材關(guān)于資源的部分(尤其是那些圖)完全不適用。

            * 暫時你只能用24bit BMP 圖像。如果讀8bit BMP文件要寫很多額外的code。我很希望聽到你們誰有更小的/更好的loader。我這里的讀入8bit 和 24bit BMP 的code實(shí)在臃腫。用LoadImage就可以。


             


            打開文件,點(diǎn)擊“插入”菜單,選“資源”


             
            然后選擇你要插入的資源類型BITMAP文件,單擊"插入"

             
            然后是文件窗口,進(jìn)入DATA目錄,選中三個圖形文件(用Ctrl啦)然后點(diǎn)“讀入”。注意文件類型是否正確。
             
            接下來會彈出三次警告(一個文件一次),說讀入正確,但該文件不能被瀏覽或編輯,因?yàn)樗卸嘤?56種顏色。沒什么的!
             


            一旦所有圖形都調(diào)入,將會出現(xiàn)一個列表。每個圖分配有一個ID,每個ID都是IDB_BITMAP打頭的,然后數(shù)字1-3。你要是懶得改,就不用管它了。不過我們還都比較勤快!


             


            右健單擊每個ID,選"屬性",然后重命名,使之與文件名匹配。就像我圖片上那樣。


             


            接下來,選“文件--〉全部保存”。你剛剛創(chuàng)建一個新的資源文件,所以Windows會問你取什么名字。你隨便拉,也可以叫"lesson38.rc" , 然后保存。
            到此為止,你有了一個資源文件,里面全是保存在硬盤上的Bitmap 圖形文件,要使用這些文件,你還需要完成一系列步驟。




             


            接下來該把資源文件加到你自己的項(xiàng)目里面了。選“項(xiàng)目--〉添加到項(xiàng)目--〉文件”


             


            選擇resorce.h文件和資源文件Lesson38.rc(用Ctrl)


             


            最后確認(rèn)資源文件Lesson38.rc放入RESOURCE FILES文件夾。就像上面圖片里那樣,點(diǎn)擊并拖入RESOURCE FILES文件夾就好了。
            移動之后選“文件--〉全部保存”,然后文件部分就好了。好多的圖阿:)

            然后我們開始code的部分。下面一段最重要的一行是#include "resource.h".沒有這行,編譯的時候就會有無數(shù)未定義變量的錯誤。resource.h文件定義了資源文件里的對象。所以要從IDB_BUTTERFLY1里面讀取數(shù)據(jù)的話,最好include這個頭文件 !

               
              

            #include <windows.h>           
            #include <gl\gl.h>                                       
            #include <gl\glu.h>                                       
            #include <gl\glaux.h>                                       
            #include "NeHeGL.h"                                   
            #include "resource.h"                                        // 資源文件的頭文件

            #pragma comment( lib, "opengl32.lib" )                               
            #pragma comment( lib, "glu32.lib" )                               
            #pragma comment( lib, "glaux.lib" )                               

            GL_Window*    g_window;
            Keys*        g_keys;

              
             下面一段第一行分配三個紋理所需空間,接下來的結(jié)構(gòu)體用于保存關(guān)于約50個在屏幕上運(yùn)動的物體的信息。
            tex將跟蹤每個物體所用紋理,x是物體的x坐標(biāo),y是y坐標(biāo),z,z坐標(biāo),yi是一個隨機(jī)數(shù)用來控制物體下落速度,
            spinz用來控制沿z軸的旋轉(zhuǎn),spinzi是另一個隨機(jī)樹,記錄旋轉(zhuǎn)速度。flap用來控制物體的翅膀(一會在解釋這個)隨機(jī)數(shù)fi控制翅膀拍打的速度。
             
              

            // 定義三個保存紋理變量的ID
            GLuint texture[3];                                            // 保存三個紋理

            struct object                                            // 定義一個物體
            {
                int   tex;                                        // 紋理值
                float x;                                            // 位置
                float y;                                       
                float z;                                       
                float yi;                                            // 速度
                float spinz;                                        // 沿Z軸旋轉(zhuǎn)的角度和速度
                float spinzi;                                       
                float flap;                                        // 是否翻轉(zhuǎn)三角形
                float fi;                                       
            };

            object obj[50];                                            // 創(chuàng)建50個物體

              
             下面一段代碼是物體obj[loop]的初始化,loop從0到49(表示50個物體中的一個)。首先是隨機(jī)紋理從0到2表示
            一個隨機(jī)著色的蝴蝶。x坐標(biāo)隨機(jī)的取-17.0f到+17.0f之間的值,y取18.0f,也就是從屏幕的上面一點(diǎn)點(diǎn)開始,
            這樣一開始時看不到物體的。z也是-10.0f到-40.f之間的隨機(jī)數(shù),spinzi取-1.0f到1.0f之間。flap取翅膀中心
            位置,為0.0f。最后拍打速度fi和下落速度yi也是隨機(jī)的。
             
              

            void SetObject(int loop)                                    // 循環(huán)設(shè)置50個物體
            {
                obj[loop].tex=rand()%3;                                // 紋理
                obj[loop].x=rand()%34-17.0f;                            // 位置
                obj[loop].y=18.0f;                                   
                obj[loop].z=-((rand()%30000/1000.0f)+10.0f);                       
                obj[loop].spinzi=(rand()%10000)/5000.0f-1.0f;                        // 旋轉(zhuǎn)
                obj[loop].flap=0.0f;                                   
                obj[loop].fi=0.05f+(rand()%100)/1000.0f;                       
                obj[loop].yi=0.001f+(rand()%1000)/10000.0f;                       
            }

              
             這回該到了最有意思的地方了。從資源文件中讀入bitmap,轉(zhuǎn)為紋理。hBMP是指向這個bitmap文件的指針,
            它將告訴我們的程序從哪里讀取數(shù)據(jù)。BMP是一個bitmap結(jié)構(gòu)體,我們把從資源文件中讀取的數(shù)據(jù)保存在里面。
            第三行是告訴我們的程序我們將使用哪些ID:IDB_BUTTERFLY1,IDB_BUTTERFLY2,IDB_BUTTERFLY3。要用更多
            的圖像的話,只需增加資源文件中的圖像,并在Texture[]中增加新的ID。
             
              

            void LoadGLTextures()                                        // 資源文件中讀入bitmap,轉(zhuǎn)為紋理
            {
                HBITMAP hBMP;                                        // 位圖句柄
                BITMAP    BMP;                                        // 位圖結(jié)構(gòu)

                // 紋理句柄
                byte    Texture[]={ IDB_BUTTERFLY1, IDB_BUTTERFLY2, IDB_BUTTERFLY3 };

              
             下面一行使用sizeof(Texture)來計算要創(chuàng)建多少個紋理。我們有3個ID,也就是3個紋理。 
              

                glGenTextures(sizeof(Texture), &texture[0]);                            // 創(chuàng)建三個紋理
                for (int loop=0; loop<sizeof(Texture); loop++)                        // 循環(huán)載入所有的位圖
                {

              
             LoadImage需要如下參數(shù):GetModuleHandle(NULL)-指向?qū)嵗木浔琈AKEINTRESOURCE(Texture[loop])-把Texture[loop]從整型轉(zhuǎn)為一個資
            源值,也就是要讀的圖形文件。IMAGE_BITMAP-告訴我們要讀的是一個bitmap文件。
            接下來兩個參數(shù)(0,0)是讀入圖像的高度和寬度像素數(shù),使用默認(rèn)大小就設(shè)為0。
            最后一個參數(shù)(LR_CREATEDIBSECTION)返回DIB section bitmap??這是一個沒有保存顏色信息的bitmap。也正是我們需要的。
            hBMP 指向從LoadImage()讀入的bitmap數(shù)據(jù)。
             
              

                    hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(Texture[loop]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

              
             檢查指針hBMP是否有效,即指向有用數(shù)據(jù)。如果沒有指向任何數(shù)據(jù),也可以彈出錯誤提示。
            如果數(shù)據(jù)存在,用GetObject()從hBMP取得數(shù)據(jù)(sizeof(BMP))并存儲在BMP中。
            glPixelStorei告訴OpenGL這些數(shù)據(jù)是以word alignments存儲的,也就是每像素4字節(jié)。
            綁定紋理,設(shè)置濾波方式為GL_LINEAR_MIPMAP_LINEAR(又好又光滑),然后生成紋理。
            注意到我們使用BMP.bmWidth和BMP.bmHeight獲取圖像的高度和寬度。并用GL_BGR_EXT交換紅藍(lán),實(shí)際使用的資源數(shù)據(jù)是從BMP.bmBits中取得的

            最后刪除bitmap對象,釋放所有與之相聯(lián)系的系統(tǒng)資源空間。
             
              

                    if (hBMP)                                    // 位圖是否存在
                    {                                    // 存在
                        GetObject(hBMP,sizeof(BMP), &BMP);                    // 獲得位圖
                        glPixelStorei(GL_UNPACK_ALIGNMENT,4);                // 以四字節(jié)方式對其內(nèi)存
                        glBindTexture(GL_TEXTURE_2D, texture[loop]);                // 綁定位圖
                        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);        // 設(shè)置紋理過濾器
                        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
                    // 創(chuàng)建紋理
                        gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
                        DeleteObject(hBMP);                        // 刪除位圖對象
                    }
                }
            }

              
             init code沒有什么新鮮的,只是增加了LoadGLTextures()調(diào)用上面的code。清屏的顏色是黑色,不進(jìn)行深度檢測,這樣比較快。啟用紋理映
            射和混色效果。
             
              

            BOOL Initialize (GL_Window* window, Keys* keys)                            // 初始化
            {
                g_window    = window;
                g_keys        = keys;

                LoadGLTextures();                                        //載入紋理

                glClearColor (0.0f, 0.0f, 0.0f, 0.5f);                            // 設(shè)置背景
                glClearDepth (1.0f);                                   
                glDepthFunc (GL_LEQUAL);                               
                glDisable(GL_DEPTH_TEST);                                    // 啟用深度測試
                glShadeModel (GL_SMOOTH);                               
                glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);               
                glEnable(GL_TEXTURE_2D);                                    // 啟用2D紋理
                glBlendFunc(GL_ONE,GL_SRC_ALPHA);                                // 使用混合
                glEnable(GL_BLEND);                                   
              
             初始化所有的物體 
              

                for (int loop=0; loop<50; loop++)
                {
                    SetObject(loop);                           
                }

                return TRUE;                                        // 成功返回
            }

            void Deinitialize (void)                                   
            {
            }

            void Update (DWORD milliseconds)                                    // 更新,執(zhí)行動畫
            {
                if (g_keys->keyDown [VK_ESCAPE] == TRUE)                            // 按ESC退出
                {
                    TerminateApplication (g_window);                       
                }

                if (g_keys->keyDown [VK_F1] == TRUE)                                // 按F1切換顯示模式
                {
                    ToggleFullscreen (g_window);                           
                }
            }

              
             接下來看看繪制代碼。在這部分我將講解如何用盡可能簡單的方式將一個圖像映到兩個三角形上。有些人認(rèn)為有理由相信,一個圖像到三角形
            上的單一映射是不可能的。
            實(shí)際上,你可以輕而易舉地將圖像映到任何形狀的區(qū)域內(nèi)。使得圖像與邊界匹配或者完全不考慮形式。根本沒關(guān)系的。(譯者:我想作者的意
            思是,從長方形到三角形的解析影射是不存在的,但不考慮那么多的話,任意形狀之間的連續(xù)影射總是可以存在的。他說的使紋理與邊界匹配
            ,大概是指某一種參數(shù)化的方法,簡單地說使得扭曲最小。)
            首先清屏,循環(huán)潤色50個蝴蝶對象。
             
              

            void Draw (void)                                        // 繪制場景
            {
                glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                   

                for (int loop=0; loop<50; loop++)                           
                {

              
             調(diào)用glLoadIdentify()重置投影矩陣,然后選擇對象的紋理。用glTranslatef()為蝴蝶定位,然后沿x軸旋轉(zhuǎn)45度。使之向觀眾微略傾斜,這
            樣比較有立體感。最后沿z軸旋轉(zhuǎn),蝴蝶就旋轉(zhuǎn)下落了。
             
              

                    glLoadIdentity ();                                // 重置矩陣
                    glBindTexture(GL_TEXTURE_2D, texture[obj[loop].tex]);                // 綁定紋理
                    glTranslatef(obj[loop].x,obj[loop].y,obj[loop].z);                // 繪制物體
                    glRotatef(45.0f,1.0f,0.0f,0.0f);                       
                    glRotatef((obj[loop].spinz),0.0f,0.0f,1.0f);                   
              
             其實(shí)到三角形上的映射和到方形上并沒有很大區(qū)別。只是你只有三個定點(diǎn),要小心一點(diǎn)。
            下面的code中,我們將會值第一個三角形。從一個設(shè)想的方形的右上角開始,到左上角,再到左下角。潤色的結(jié)果像下面這樣:



             


            注意半個蝴蝶出現(xiàn)了。另外半個出現(xiàn)在第二個三角形里。同樣地將三個紋理坐標(biāo)與頂點(diǎn)坐標(biāo)非別對應(yīng),這給出充分的信息定義一個三角形上的映射。
             
              

                    glBegin(GL_TRIANGLES);   

                        glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);           
                        glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f, 1.0f, obj[loop].flap);   
                        glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);           
              
             下面的code潤色另一半。同上,只是我們的三角變成了從右上到左下,再到右下。
             
            第一個三角形的第二點(diǎn)和第二個三角形的第三點(diǎn)(也就是翅膀的尖端)在z方向往復(fù)運(yùn)動(即z=-1.0f和1.0f之間),兩個三角形沿著蝴蝶的身
            體折疊起來,產(chǎn)生拍打的效果,簡易可行。
             
              

                        glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);           
                        glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);           
                        glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f,-1.0f, obj[loop].flap);   

                    glEnd();               

              
             下面一段通過從obj[loop].y中遞減obj[loop].yi使蝴蝶自上而下運(yùn)動。spinz值遞增spinzi(可正可負(fù))flap遞增fi.fi的正負(fù)取決于翅膀向
            上還是向下運(yùn)動。
             
              

                    //移動,選擇圖像
                    obj[loop].y-=obj[loop].yi;                           
                    obj[loop].spinz+=obj[loop].spinzi;                       
                    obj[loop].flap+=obj[loop].fi;                           

              
             當(dāng)蝴蝶向下運(yùn)行時,需要檢查是否越出屏幕,如果是,就調(diào)用SetObject(loop)來給蝴蝶賦新的紋理,新下落速度等。  
              

                    if (obj[loop].y<-18.0f)                                //判斷是否超出了屏幕,如果是重置它
                    {
                        SetObject(loop);                           
                    }

              
             翅膀拍打的時候,還要檢查flap是否小于-1.0f或大于1.0f,如果是,令fi=-fi,以改變運(yùn)動方向。Sleep(15)是用來減緩運(yùn)行速度,每幀15毫
            秒。在我朋友的機(jī)器上,這讓蝴蝶瘋狂的飛舞。不過我懶得改了:)
             
              

                    if ((obj[loop].flap>1.0f) || (obj[loop].flap<-1.0f))               
                    {
                        obj[loop].fi=-obj[loop].fi;
                    }
                }

                Sleep(15);                                       

                glFlush ();                                   
            }

              
             希望你在這一課學(xué)的開心。也希望通過這一課,從資源文件里讀取紋理,和三角形映射的過程變得比較容易理解。我花五分鐘又沖讀了一遍,
            感覺還好。如果你還有什么問題,盡管問。我希望我的講義盡可能好,因此期待您的任何回應(yīng)。

             
             
            posted on 2007-12-25 15:20 sdfasdf 閱讀(974) 評論(0)  編輯 收藏 引用 所屬分類: OPENGL
            久久精品无码一区二区三区免费| 91精品国产乱码久久久久久 | 精品国产一区二区三区久久| 久久笫一福利免费导航| 国产福利电影一区二区三区久久老子无码午夜伦不| 国产成人无码精品久久久性色| 香蕉99久久国产综合精品宅男自| 久久婷婷五月综合成人D啪| 欧洲性大片xxxxx久久久| 色婷婷狠狠久久综合五月| 久久99国产一区二区三区| 久久精品国产精品亚洲下载| 久久国产精品偷99| 亚洲精品午夜国产va久久| 久久精品卫校国产小美女| 久久亚洲私人国产精品vA| 狠狠色婷婷久久一区二区三区| 久久最新精品国产| 久久免费视频一区| 亚洲AV无码久久寂寞少妇| 国产精品久久久久国产A级| 狠狠色综合网站久久久久久久| 久久婷婷五月综合成人D啪| 亚洲午夜久久久影院伊人| 99久久99久久久精品齐齐| 久久久久18| 久久精品国产亚洲AV香蕉| 久久99精品久久久久久秒播| 国内精品久久久久影院老司| 九九久久99综合一区二区| 欧美久久久久久午夜精品| 中文国产成人精品久久不卡| 亚洲精品高清久久| 国产69精品久久久久观看软件| 久久国产精品一国产精品金尊| 久久久精品国产亚洲成人满18免费网站 | 亚洲午夜无码久久久久| 国产一区二区精品久久凹凸| 日韩人妻无码精品久久免费一| 久久不见久久见免费影院www日本| 亚洲中文精品久久久久久不卡|