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

            常用鏈接

            留言簿(48)

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

            搜索

            •  

            積分與排名

            • 積分 - 398977
            • 排名 - 59

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            嗨,我是Dario Corno,也因SpinningKids的rIo而為大家所知。首先,我想要解釋我為什么決定寫這點(diǎn)指南。我自1989年以來(lái)就從事scener的工作。我想要你們?nèi)ハ螺d一些demo(示例程序,也就是演示——譯者)以幫助你理解什么是Demo并且demo的效果是什么。
            Demos是被用來(lái)展示恰似風(fēng)雅的技術(shù)一樣無(wú)限并且時(shí)而嚴(yán)酷的譯碼。在今天的演示中你通常總可以發(fā)現(xiàn)一些真正迷人的效果。這不是一本迷人的效果指南,但結(jié)果將非常的酷!你能夠從http://www.pouet.net和 http://ftp.scene.org. 發(fā)現(xiàn)大量的演示收集。
            既然緒論超出了我們探討的范圍,我們可以繼續(xù)我們的指南了。
            我將解釋如何做一個(gè)看起來(lái)象徑向模糊的eye candy 效果。有時(shí)它以測(cè)定體積的光線被提到。不要相信,它僅僅是一個(gè)冒牌的輻射狀模糊;D
            輻射狀模糊效果通常借助于模糊在一個(gè)方向上相對(duì)于模糊物的中心原始圖象的每一個(gè)象素來(lái)做的。
            借助于現(xiàn)今的硬件用色彩緩沖器來(lái)手工作模糊處理是極其困難的(至少在某種程度上它被所有的gfx卡所支持),因此我們需要一些竅門來(lái)達(dá)到同樣的效果。
            作為一個(gè)獎(jiǎng)勵(lì)當(dāng)學(xué)習(xí)徑向模糊效果時(shí),你同樣將學(xué)到如何輕松地提供材料的紋理。
            我決定在這篇指南中使用彈簧作為外形因?yàn)樗且粋€(gè)酷的外形,另外還因?yàn)槲覍?duì)立方體感到厭煩:}
            多留意這篇指南關(guān)于如何創(chuàng)建那個(gè)效果的指導(dǎo)方針是重要的。我不研究解釋那些代碼的詳情。你應(yīng)當(dāng)用心記下它們中的大部分:}
            下面是變量的定義和用到的頭文件。

             
              

            #include <math.h>                                // 數(shù)學(xué)庫(kù)

            float        angle;                            // 用來(lái)旋轉(zhuǎn)那個(gè)螺旋
            float        vertexes[3][3];                        // 為3個(gè)設(shè)置的頂點(diǎn)保存浮點(diǎn)信息
            float        normal[3];                        // 存放法線數(shù)據(jù)的數(shù)組
            GLuint        BlurTexture;                        // 存放紋理編號(hào)的一個(gè)無(wú)符號(hào)整型

              
             函數(shù)EmptyTexture()創(chuàng)建了一個(gè)空的紋理并返回紋理的編號(hào)。我們剛分配了一些自由空間(準(zhǔn)確的是128*128*4無(wú)符號(hào)整數(shù))。
            128*128是紋理的大小(128象素寬和高),4意味著為每一個(gè)象素我們想用4byte來(lái)存儲(chǔ)紅,綠,藍(lán)和ALPHA組件。
             
              

            GLuint EmptyTexture()                            // 創(chuàng)建一個(gè)空的紋理
            {
                GLuint txtnumber;                            // 紋理ID
                unsigned int* data;                        // 存儲(chǔ)數(shù)據(jù)

                // 為紋理數(shù)據(jù)(128*128*4)建立存儲(chǔ)區(qū)
                data = (unsigned int*)new GLuint[((128 * 128)* 4 * sizeof(unsigned int))];

              
             在分配完空間之后我們用ZeroMemory函數(shù)清0,返回指針(數(shù)據(jù))和被清0的存貯區(qū)的大小。
            另一半需注意的重要的事情是我們?cè)O(shè)置GL_LINEAR的放大率和縮放率的方法。因?yàn)槲覀儗⒈晃覀兊募y理要求投入全部的精力并且如果被濫用,GL_NEAREST會(huì)看起來(lái)非常糟糕。
             
              

                ZeroMemory(data,((128 * 128)* 4 * sizeof(unsigned int)));    // 清除存儲(chǔ)區(qū)

                glGenTextures(1, &txtnumber);                // 創(chuàng)建一個(gè)紋理
                glBindTexture(GL_TEXTURE_2D, txtnumber);            // 構(gòu)造紋理
                glTexImage2D(GL_TEXTURE_2D, 0, 4, 128, 128, 0,
                    GL_RGBA, GL_UNSIGNED_BYTE, data);            // 用數(shù)據(jù)中的信息構(gòu)造紋理
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

                delete [] data;                        // 釋放數(shù)據(jù)

                return txtnumber;                        // 返回紋理ID
            }

              
             這個(gè)函數(shù)簡(jiǎn)單規(guī)格化法線向量的長(zhǎng)度。向量被當(dāng)作有3個(gè)浮點(diǎn)類型的元素的數(shù)組來(lái)表示,第一個(gè)元素表示X軸,第二個(gè)表示Y,第三個(gè)表示Z。一個(gè)規(guī)格化的向量[Nv]被Vn表達(dá)為Vn=[Vox/|Vo|,Voy/|Vo|,Voz/|Vo|],這里Vo是最初的向量,|Vo|是該向量的系數(shù)(或長(zhǎng)度),X,Y,Z它的組件。之后由向量的長(zhǎng)度區(qū)分每一個(gè)法線向量組件。
             
              

            void ReduceToUnit(float vector[3])                    // 歸一化一個(gè)法向量
            {                                // 一定長(zhǎng)度的單位法線向量
                float length;                        // 保存長(zhǎng)度
                // 計(jì)算向量
                length = (float)sqrt((vector[0]*vector[0]) + (vector[1]*vector[1]) + (vector[2]*vector[2]));

                if(length == 0.0f)                        // 避免除0錯(cuò)誤
                    length = 1.0f;                    // 如果為0設(shè)置為1

                vector[0] /= length;                    // 歸一化向量
                vector[1] /= length;                       
                vector[2] /= length;                       
            }

              
             下面各項(xiàng)計(jì)算所給的3個(gè)頂點(diǎn)向量(總在3個(gè)浮點(diǎn)數(shù)組中)。我們有兩個(gè)參數(shù):v[3][3]和out[3]。當(dāng)然第一個(gè)參數(shù)是一個(gè)m=3,n=3每一行代表三角形一個(gè)頂點(diǎn)的浮點(diǎn)矩陣。Out是我們要放置作為結(jié)果的法線向量的位置。
            相當(dāng)簡(jiǎn)單的數(shù)學(xué)。我們將使用著名的交叉乘積運(yùn)算。理論上說交叉乘積是兩個(gè)向量——它返回另一個(gè)直交向量到兩個(gè)原始向量——之間的操作。法線向量是一個(gè)垂直物體表面的直交向量,是與該表面相對(duì)的(通常一個(gè)規(guī)格化的長(zhǎng)度)。設(shè)想兩個(gè)向量是在一個(gè)三角形的一側(cè)的上方,那么這個(gè)三角形兩邊的直交向量(由交叉乘積計(jì)算)就是那個(gè)三角形的法線。
            解釋比實(shí)行還難。
            我們將著手從現(xiàn)存的頂點(diǎn)0到頂點(diǎn)1,從頂點(diǎn)1到頂點(diǎn)2找到那個(gè)向量。這是基本上通過減法——下一個(gè)頂點(diǎn)的每個(gè)組件減一個(gè)頂點(diǎn)的每個(gè)組件——作好了的。現(xiàn)在我們已經(jīng)為我們的三角形的邊找到了那個(gè)向量。通過交叉相乘我們?yōu)槟莻€(gè)三角形找到了法線向量。
            看代碼。
            V[0][ ]是第一個(gè)頂點(diǎn),v[1][ ]是第二個(gè)頂點(diǎn),v[2][ ]是第三個(gè)頂點(diǎn)。每個(gè)頂點(diǎn)包括:v[ ][0]是頂點(diǎn)的x坐標(biāo),v[ ][1]是頂點(diǎn)的y坐標(biāo),v[ ][2]是頂點(diǎn)的z坐標(biāo)。
            通過簡(jiǎn)單的減法從一個(gè)頂點(diǎn)的每個(gè)坐標(biāo)到另一個(gè)頂點(diǎn)每個(gè)坐標(biāo)我們得到了那個(gè)VECTOR。v1[0] = v[0][0] - v[1][0],這計(jì)算現(xiàn)存的從一個(gè)頂點(diǎn)到另一個(gè)頂點(diǎn)的向量的X組件,v1[1] = v[0][1] - v[1][1]將計(jì)算Y組件,v1[2] = v[0][2] - v[1][2] 計(jì)算Z組件等等。
            現(xiàn)在我們有了兩個(gè)向量,所以我們計(jì)算它們的交叉乘積得到那個(gè)三角形的法線。
            交叉相乘的規(guī)則是:
            out[x] = v1[y] * v2[z] - v1[z] * v2[y]

            out[y] = v1[z] * v2[x] - v1[x] * v2[z]

            out[z] = v1[x] * v2[y] - v1[y] * v2[x]


            我們最終得到了這個(gè)三角形的法線in out[ ]。

             
              

            void calcNormal(float v[3][3], float out[3])                // 用三點(diǎn)計(jì)算一個(gè)立方體法線
            {
                float v1[3],v2[3];                        // 向量 1 (x,y,z) 和向量 2 (x,y,z)
                static const int x = 0;                    // 定義 X坐標(biāo)
                static const int y = 1;                    // 定義 Y 坐標(biāo)
                static const int z = 2;                    // 定義 Z 坐標(biāo)

            // 用減法在兩點(diǎn)之間得到向量// 從一點(diǎn)到另一點(diǎn)的X,Y,Z坐標(biāo)// 計(jì)算點(diǎn)1到點(diǎn)0的向量
                v1[x] = v[0][x] - v[1][x];                   
                v1[y] = v[0][y] - v[1][y];                   
                v1[z] = v[0][z] - v[1][z];                   
                // 計(jì)算點(diǎn)2到點(diǎn)1的向量
                v2[x] = v[1][x] - v[2][x];                   
                v2[y] = v[1][y] - v[2][y];                   
                v2[z] = v[1][z] - v[2][z];                   
                // 計(jì)算交叉乘積為我們提供一個(gè)表面的法線
                out[x] = v1[y]*v2[z] - v1[z]*v2[y];               
                out[y] = v1[z]*v2[x] - v1[x]*v2[z];               
                out[z] = v1[x]*v2[y] - v1[y]*v2[x];               

                ReduceToUnit(out);                        //  規(guī)格化向量
            }

              
             下面的例子正好用gluLookAt設(shè)立了一個(gè)觀察點(diǎn)。我們?cè)O(shè)置一個(gè)觀察點(diǎn)放置在0,5,50位置——正照看0,0,0并且所屬的向上的向量正仰望(0,1,0)!:D 
              

            void ProcessHelix()                            // 繪制一個(gè)螺旋
            {
                GLfloat x;                            // 螺旋x坐標(biāo)
                GLfloat y;                            // 螺旋y坐標(biāo)
                GLfloat z;                            // 螺旋z坐標(biāo)
                GLfloat phi;                            // 角
                GLfloat theta;                            // 角
                GLfloat v,u;                            // 角
                GLfloat r;                            // 螺旋半徑
                int twists = 5;                            // 5個(gè)螺旋

                GLfloat glfMaterialColor[]={0.4f,0.2f,0.8f,1.0f};            // 設(shè)置材料色彩
                GLfloat specular[]={1.0f,1.0f,1.0f,1.0f};                // 設(shè)置鏡象燈光

                glLoadIdentity();                            // 重置Modelview矩陣
                gluLookAt(0, 5, 50, 0, 0, 0, 0, 1, 0);                // 場(chǎng)景(0,0,0)的視點(diǎn)中心 (0,5,50),Y軸向上
                                               
                glPushMatrix();                            // 保存Modelview矩陣

                glTranslatef(0,0,-50);                        // 移入屏幕50個(gè)單位
                glRotatef(angle/2.0f,1,0,0);                    // 在X軸上以1/2角度旋轉(zhuǎn)
                glRotatef(angle/3.0f,0,1,0);                    // 在Y軸上以1/3角度旋轉(zhuǎn)

                glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,glfMaterialColor);
                glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular);

              
             然后我們計(jì)算螺旋的公式并給彈簧著色。十分簡(jiǎn)單,我就不再解釋了,因?yàn)樗皇沁@篇指南的主要目的。這段螺旋代碼經(jīng)過軟件贊助者的許可被借用(并作了一點(diǎn)優(yōu)化)。這是寫作的簡(jiǎn)單的方法,但不是最塊的方法。使用頂點(diǎn)數(shù)組可以使它更快! 
              

                r=1.5f;                            // 半徑

                glBegin(GL_QUADS);                        // 開始繪制立方體
                for(phi=0; phi <= 360; phi+=20.0)                // 以20度的間隔繪制
                {
                    for(theta=0; theta<=360*twists; theta+=20.0)       
                    {
                        v=(phi/180.0f*3.142f);            // 計(jì)算第一個(gè)點(diǎn) ( 0 )的角度
                        u=(theta/180.0f*3.142f);            // 計(jì)算第一個(gè)點(diǎn) ( 0 )的角度

                        x=float(cos(u)*(2.0f+cos(v) ))*r;        // 計(jì)算x的位置(第一個(gè)點(diǎn))
                        y=float(sin(u)*(2.0f+cos(v) ))*r;        // 計(jì)算y的位置(第一個(gè)位置)
                        z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);    // 計(jì)算z的位置(第一個(gè)位置)

                        vertexes[0][0]=x;                // 設(shè)置第一個(gè)頂點(diǎn)的x值
                        vertexes[0][1]=y;                // 設(shè)置第一個(gè)頂點(diǎn)的y值
                        vertexes[0][2]=z;                // 設(shè)置第一個(gè)頂點(diǎn)的z值

                        v=(phi/180.0f*3.142f);            // 計(jì)算第二個(gè)點(diǎn)( 0 )的角度
                        u=((theta+20)/180.0f*3.142f);        // 計(jì)算第二個(gè)點(diǎn)( 20 )的角度

                        x=float(cos(u)*(2.0f+cos(v) ))*r;        // 計(jì)算x位置(第二個(gè)點(diǎn))
                        y=float(sin(u)*(2.0f+cos(v) ))*r;        // 計(jì)算y位置(第二個(gè)點(diǎn))
                        z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);    // 計(jì)算z位置(第二個(gè)點(diǎn))

                        vertexes[1][0]=x;                // 設(shè)置第二個(gè)頂點(diǎn)的x值
                        vertexes[1][1]=y;                // 設(shè)置第二個(gè)頂點(diǎn)的y值
                        vertexes[1][2]=z;                // 設(shè)置第二個(gè)頂點(diǎn)的z值

                        v=((phi+20)/180.0f*3.142f);            // 計(jì)算第三個(gè)點(diǎn) ( 20 )的角度
                        u=((theta+20)/180.0f*3.142f);        // 計(jì)算第三個(gè)點(diǎn) ( 20 )的角度

                        x=float(cos(u)*(2.0f+cos(v) ))*r;        // 計(jì)算x位置 (第三個(gè)點(diǎn))
                        y=float(sin(u)*(2.0f+cos(v) ))*r;        // 計(jì)算y位置 (第三個(gè)點(diǎn))
                        z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);    // 計(jì)算z位置 (第三個(gè)點(diǎn))

                        vertexes[2][0]=x;                // 設(shè)置第三個(gè)頂點(diǎn)的x值
                        vertexes[2][1]=y;                // 設(shè)置第三個(gè)頂點(diǎn)的y值
                        vertexes[2][2]=z;                // 設(shè)置第三個(gè)頂點(diǎn)的z值

                        v=((phi+20)/180.0f*3.142f);            // 計(jì)算第四個(gè)點(diǎn)( 20 )的角度
                        u=((theta)/180.0f*3.142f);            // 計(jì)算第四個(gè)點(diǎn)( 0 )的角度

                        x=float(cos(u)*(2.0f+cos(v) ))*r;        // 計(jì)算x位置 (第四個(gè)點(diǎn))
                        y=float(sin(u)*(2.0f+cos(v) ))*r;        // 計(jì)算y位置 (第四個(gè)點(diǎn))
                        z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);    // 計(jì)算z位置 (第四個(gè)點(diǎn)))

                        vertexes[3][0]=x;                // 設(shè)置第四個(gè)頂點(diǎn)的x值
                        vertexes[3][1]=y;                // 設(shè)置第四個(gè)頂點(diǎn)的y值
                        vertexes[3][2]=z;                // 設(shè)置第四個(gè)頂點(diǎn)的z值

                        calcNormal(vertexes,normal);        // 計(jì)算立方體的法線

                        glNormal3f(normal[0],normal[1],normal[2]);    // 設(shè)置法線

                        // 渲染四邊形
                        glVertex3f(vertexes[0][0],vertexes[0][1],vertexes[0][2]);
                        glVertex3f(vertexes[1][0],vertexes[1][1],vertexes[1][2]);
                        glVertex3f(vertexes[2][0],vertexes[2][1],vertexes[2][2]);
                        glVertex3f(vertexes[3][0],vertexes[3][1],vertexes[3][2]);
                    }
                }
                glEnd();                            // 繪制結(jié)束

                glPopMatrix();                        // 取出矩陣
            }

              
             這兩個(gè)事例(ViewOrtho and ViewPerspective)被編碼以使它變得很容易地在一個(gè)直交的情形下繪制并且不費(fèi)力的返回透視圖。
            ViewOrtho簡(jiǎn)單地設(shè)立了這個(gè)射影矩陣,然后增加一份現(xiàn)行射影矩陣的拷貝到OpenGL棧上。這個(gè)恒等矩陣然后被裝載并且當(dāng)前屏幕正投影觀察決議被提出。
            利用2維坐標(biāo)以屏幕左上角0,0和屏幕右下角639,479來(lái)繪制是可能的。
            最后,modelview矩陣為透視材料激活。
            ViewPerspective設(shè)置射影矩陣模式取回ViewOrtho在堆棧上推進(jìn)的非正交矩陣。然后樣本視圖被選擇因此我們可以透視材料。
            我建議你保留這兩個(gè)過程,能夠著色2D而不需擔(dān)心射影矩陣很不錯(cuò)。 
              

            void ViewOrtho()                            // 設(shè)置一個(gè)z正視圖
            {
                glMatrixMode(GL_PROJECTION);                // 選擇投影矩陣
                glPushMatrix();                        // 保存當(dāng)前矩陣
                glLoadIdentity();                        // 重置矩陣
                glOrtho( 0, 640 , 480 , 0, -1, 1 );                // 選擇標(biāo)準(zhǔn)模式
                glMatrixMode(GL_MODELVIEW);                    // 選擇樣本視圖矩陣
                glPushMatrix();                        // 保存當(dāng)前矩陣
                glLoadIdentity();                        // 重置矩陣
            }

            void ViewPerspective()                            // 設(shè)置透視視圖
            {
                glMatrixMode( GL_PROJECTION );                    // 選擇投影矩陣
                glPopMatrix();                            // 取出矩陣
                glMatrixMode( GL_MODELVIEW );                    // 選擇模型變換矩陣
                glPopMatrix();                            //彈出矩陣
            }

              
             現(xiàn)在是解釋那個(gè)冒牌的輻射狀的模糊效果是如何作的時(shí)候了。
            我們需要繪制這個(gè)場(chǎng)景——它從中心開始在所有方向上模糊出現(xiàn)。竅門是在沒有主要的性能瓶頸的情況下做出的。我們不能讀寫象素,并且如果我們想和非kick-butt視頻卡兼容,我們不能使用擴(kuò)展名何驅(qū)動(dòng)程序特殊命令。
            沒辦法了嗎?
            不,解決方法非常簡(jiǎn)單,OpenGL賦予我們“模糊”紋理的能力。OK……并非真正的模糊,但我們利用線性過濾去依比例決定一個(gè)紋理,結(jié)果(有些想象成分)看起來(lái)象高斯模糊。
            因此如果我們正確地在3D場(chǎng)景中放了大量的被拉伸的紋理并依比例決定會(huì)有什么發(fā)生?
            答案比你想象的還簡(jiǎn)單。
            問題一:透視一個(gè)紋理
            有一個(gè)后緩沖器在象素格式下問題容易解決。在沒有后緩沖器的情況下透視一個(gè)紋理在眼睛看來(lái)是一個(gè)真正的痛苦。
            透視紋理剛好借助一個(gè)函數(shù)來(lái)完成。我們需要繪制我們的實(shí)體然后利用glCopytexImage函數(shù)復(fù)制這個(gè)結(jié)果(在交換前,后緩沖器之前)后到紋理。
            問題二:在3D實(shí)體前精確地協(xié)調(diào)紋理。
            我們知道:如果我們?cè)跊]有設(shè)置正確的透視的情況下改變了視口,我們就得到一個(gè)我們的實(shí)體的一個(gè)被拉伸的透視圖。例如如果我們?cè)O(shè)置一個(gè)是視口足夠?qū)捨覀兙偷玫揭粋€(gè)垂直地被拉伸的透視圖。
            解決方法是首先設(shè)置一個(gè)視口正如我們的紋理(128×128)。透視我們的實(shí)體到這個(gè)紋理之后,我們利用當(dāng)前屏幕決議著色這個(gè)紋理到屏幕。這種方法OpenGL縮減這個(gè)實(shí)體去適應(yīng)紋理,并且我們拉伸紋理到全屏大小時(shí),OpenGL重新調(diào)整紋理的大小去完美的適應(yīng)在我們的3d實(shí)體頂端。希望我沒有丟掉任何一點(diǎn)。另一個(gè)靈活的例子是,如果你取一個(gè)640×480大小screenshot,然后調(diào)整成為256x256的位圖,你可以以一個(gè)紋理裝載這個(gè)位圖,并拉伸它使之適合640x480的屏幕。這個(gè)質(zhì)量可能不會(huì)以前一樣好,但是這個(gè)紋理排列起的效果應(yīng)當(dāng)接近最初的640x480圖象。
            On to the fun stuff! 這個(gè)函數(shù)相當(dāng)簡(jiǎn)單,并且是我的首選的“設(shè)計(jì)竅門”之一。它設(shè)置一個(gè)與我們的BlurTexture度數(shù)相匹配的大小的視口。然后它被彈簧的著色程序調(diào)用。彈簧將由于視口被拉伸適應(yīng)128*128的紋理。
            在彈簧被拉伸至128x128視口大小之后,我們約定BlurTexture 且用glCopyTexImage2D從視口拷貝色彩緩沖器到BlurTexture。
            參數(shù)如下:
            GL_TEXTURE_2D指出我們正使用一個(gè)2Dimensional紋理,0是我們想要拷貝緩沖器到mip的繪圖等級(jí),默認(rèn)等級(jí)是0。GL_LUMINANCE指出被拷貝的數(shù)據(jù)格式。我之所以使用GL_LUMINANCE因?yàn)樽罱K結(jié)果看起來(lái)比較好。這種情形緩沖器的亮度部分將被拷貝到紋理。其它參數(shù)可以是GL_ALPHA, GL_RGB, GL_INTENSITY等等。
            其次的兩個(gè)參數(shù)告訴OpenGL從(0,0)開始拷貝到哪里。寬度和高度(128,128)是從左到右有多少象素要拷貝并且上下拷貝多少。最后一個(gè)參數(shù)僅用來(lái)指出我們是否想要一個(gè)邊界——哪個(gè)不想要。
            既然在我們的BlurTexture我們已經(jīng)有了一個(gè)色彩緩沖器的副本(和被拉伸的彈簧一致),我們可以清除那個(gè)緩沖器,向后設(shè)置那個(gè)視口到適當(dāng)?shù)亩葦?shù)(640x480全屏)。
            重要:
            這個(gè)竅門能用在只有雙緩沖器象素格式的情況下。原因是所有這些操作從觀察者面前被隱藏起來(lái)。(在后緩沖器完成)。
             
              

            void RenderToTexture()                        // 著色到一個(gè)紋理
            {
                glViewport(0,0,128,128);                    // 設(shè)置我們的視口

                ProcessHelix();                        // 著色螺旋

                glBindTexture(GL_TEXTURE_2D,BlurTexture);            // 綁定模糊紋理

                // 拷貝我們的視口到模糊紋理 (從 0,0 到 128,128... 無(wú)邊界)
                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 128, 128, 0);

                glClearColor(0.0f, 0.0f, 0.5f, 0.5);                //調(diào)整清晰的色彩到中等藍(lán)色
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        // 清屏和深度緩沖

                glViewport(0 , 0,640 ,480);                    // 調(diào)整視口 (0,0 to 640x480)
            }

              
             DrawBlur函數(shù)僅在我們的3D場(chǎng)景前繪制一些混合的方塊——用BlurTexture我們以前已實(shí)現(xiàn)。這樣,借由阿爾發(fā)和縮放這個(gè)紋理,我們得到了真正看起來(lái)象輻射狀的模糊的效果。
            我首先禁用GEN_S 和 GEN_T(我沉溺于球體影射,因此我的程序通常啟用這些指令:P)。
            我們啟用2D紋理,禁用深度測(cè)試,調(diào)整正確的函數(shù),起用混合然后約束BlurTexture。
            下一件我們要作的事情是轉(zhuǎn)換到標(biāo)準(zhǔn)視圖,那樣比較容易繪制一些完美適應(yīng)屏幕大小的方塊。這是我們?cè)?D實(shí)體頂端排列紋理的方法(通過拉伸紋理匹配屏幕比例)。這是問題二要解決的地方。
             
              

            void DrawBlur(int times, float inc)                    // 繪制模糊的圖象
            {
                float spost = 0.0f;                    // 紋理坐標(biāo)偏移量
                float alphainc = 0.9f / times;                // alpha混合的衰減量
                float alpha = 0.2f;                    // Alpha初值

            // 禁用自動(dòng)生成紋理坐標(biāo)
                glDisable(GL_TEXTURE_GEN_S);
                glDisable(GL_TEXTURE_GEN_T);

                glEnable(GL_TEXTURE_2D);                    // 啟用 2D 紋理映射
                glDisable(GL_DEPTH_TEST);                    // 深度測(cè)試不可用
                glBlendFunc(GL_SRC_ALPHA,GL_ONE);                // 設(shè)置混合模式
                glEnable(GL_BLEND);                    // 啟用混合
                glBindTexture(GL_TEXTURE_2D,BlurTexture);            // 綁定混合紋理
                ViewOrtho();                        // 切換到標(biāo)準(zhǔn)視圖

                alphainc = alpha / times;                    // 減少alpha值

              
             我們多次繪制這個(gè)紋理用于創(chuàng)建那個(gè)輻射效果, 縮放這個(gè)紋理坐標(biāo)并且每次我們做另一個(gè)關(guān)口時(shí)增大混合因數(shù) 。我們繪制25個(gè)方塊,每次按照0.015f拉伸這個(gè)紋理。 
              

                glBegin(GL_QUADS);                        // 開始繪制方塊
                    for (int num = 0;num < times;num++)            // 著色模糊物的次數(shù)
                    {
                        glColor4f(1.0f, 1.0f, 1.0f, alpha);        // 調(diào)整alpha值
                        glTexCoord2f(0+spost,1-spost);           
                        glVertex2f(0,0);               

                        glTexCoord2f(0+spost,0+spost);           
                        glVertex2f(0,480);           

                        glTexCoord2f(1-spost,0+spost);       
                        glVertex2f(640,480);               

                        glTexCoord2f(1-spost,1-spost);           
                        glVertex2f(640,0);           

                        spost += inc;                // 逐漸增加 spost (快速靠近紋理中心)
                        alpha = alpha - alphainc;            // 逐漸增加 alpha (逐漸淡出紋理)
                    }
                glEnd();                            // 完成繪制方塊

                ViewPerspective();                        // 轉(zhuǎn)換到一個(gè)透視視圖

                glEnable(GL_DEPTH_TEST);                    // 深度測(cè)試可用
                glDisable(GL_TEXTURE_2D);                    // 2D紋理映射不可用
                glDisable(GL_BLEND);                    // 混合不可用
                glBindTexture(GL_TEXTURE_2D,0);                // 釋放模糊紋理
            }

              
             瞧,這是以前從未見過的最短的繪制程序,有很棒的視覺效果!
            我們調(diào)用RenderToTexture 函數(shù)。幸虧我們視口改變這個(gè)函數(shù)才著色被拉伸的彈簧。 對(duì)于我們的紋理拉伸的彈簧被著色,并且這些緩沖器被清除。
            我們之后繪制“真正的”彈簧 (你在屏幕上看到的3D實(shí)體) 通過調(diào)用 ProcessHelix( )。
            最后我們?cè)趶椈汕懊胬L制一些混合的方塊。有織紋的方塊將被拉伸以適應(yīng)在真正的3D彈簧
            上面。

             
              

            void Draw (void)                            // 繪制場(chǎng)景
            {
                glClearColor(0.0f, 0.0f, 0.0f, 0.5);                // 將清晰的顏色設(shè)定為黑色
                glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        // 清除屏幕和深度緩沖器
                glLoadIdentity();                        // 重置視圖
                RenderToTexture();                        // 著色紋理
                ProcessHelix();                        // 繪制我們的螺旋
                DrawBlur(25,0.02f);                    // 繪制模糊效果
                glFlush ();                        // 強(qiáng)制OpenGL繪制我們所有的圖形
            }

              
             我希望你滿意這篇指南,它實(shí)在沒有比透視一個(gè)紋理講授更多其它內(nèi)容,但它是一個(gè)干脆地添加到你的3D應(yīng)用程序中有趣的效果。
            如果你有任何的注釋建議或者如果你知道一種更好的方法執(zhí)行這個(gè)效果聯(lián)系我rio@spinningkids.org。
            我也想要委托你去做一列事情(家庭作業(yè)):D
            1) 更改DrawBlur程序變?yōu)橐粋€(gè)水平的模糊之物,垂直的模糊之物和一些更好的效果。(轉(zhuǎn)動(dòng)模糊之物!)。
            2) 玩轉(zhuǎn)DrawBlur參數(shù)(添加,刪除)變?yōu)橐粋€(gè)好的程序和你的音樂同步。
            3) 用GL_LUMINANCE玩弄DrawBlur參數(shù)和一個(gè)SMALL紋理(驚人的光亮!)。
            4) 用暗色紋理代替亮色嘗試大騙(哈哈,自己造的)測(cè)定體積的陰影。
            好了,這應(yīng)該是所有的了(到此為止)。
            訪問我的站點(diǎn)http://www.spinningkids.org/rio.
            獲得更多的最新指南。

             
             
            posted on 2007-12-24 16:19 sdfasdf 閱讀(1459) 評(píng)論(1)  編輯 收藏 引用 所屬分類: OPENGL

            Feedback

            # 請(qǐng)教個(gè)問題 2008-07-13 14:41 wuchen
            請(qǐng)教個(gè)問題
            在 DrawBlur(int times, float inc) 這個(gè)函數(shù)中的紋理坐標(biāo)為什么Y方向上反向?  回復(fù)  更多評(píng)論
              

            美女写真久久影院| 伊人久久久AV老熟妇色| 久久久久久A亚洲欧洲AV冫| 亚洲精品无码久久毛片| 色狠狠久久AV五月综合| 94久久国产乱子伦精品免费 | 久久综合色区| 久久av无码专区亚洲av桃花岛| 久久综合久久久| 亚洲AV无码一区东京热久久| 精品综合久久久久久88小说| 久久精品黄AA片一区二区三区| 久久久久久A亚洲欧洲AV冫| 国产精品99久久99久久久| 亚洲精品高清一二区久久| 久久er国产精品免费观看2| 久久国产免费直播| 久久亚洲2019中文字幕| 久久久国产精品福利免费 | 久久精品久久久久观看99水蜜桃| 99久久国产综合精品五月天喷水| 一本一本久久a久久综合精品蜜桃| 久久99精品国产99久久6| 国产精品视频久久久| 久久婷婷国产综合精品| 精品久久久久久国产| 一本久道久久综合狠狠躁AV| 久久久久九国产精品| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 亚洲国产小视频精品久久久三级 | 欧美麻豆久久久久久中文| 国产真实乱对白精彩久久| 国产精品欧美久久久天天影视| 久久久久女人精品毛片| 久久亚洲AV成人出白浆无码国产| 亚洲中文久久精品无码ww16 | 久久精品国产只有精品66| 精品久久久久久无码人妻蜜桃| 国产免费久久久久久无码| 国产免费久久精品99久久| 久久精品这里只有精99品|