• <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)論排行榜

            歡迎來(lái)到第十九課.你已經(jīng)學(xué)習(xí)了很多知識(shí),并且現(xiàn)在想自己來(lái)實(shí)踐.我將在這講解一個(gè)新命令... 三角形帶(我的理解就是畫(huà)很多三角形來(lái)組合成我們要的形狀),它非常容易使用,當(dāng)畫(huà)很多三角形的時(shí)候能加快你程序的運(yùn)行速度.在本課中,我將會(huì)教你該如何做一個(gè)半復(fù)雜的微粒程序.一旦您了解微粒程序的原理后,在創(chuàng)建例如:火,煙,噴泉等效果將是很輕松的事情.我必須警告你!直到今天我從未寫(xiě)一個(gè)真正的粒子程序.我想寫(xiě)一個(gè)"出名"的復(fù)雜的粒子程序.我嘗試過(guò),但在我了解我不能控制所有點(diǎn)變瘋狂之后我放棄了!!!你也許不相信我要告訴你的,但這個(gè)課程從頭到尾都是我自己的想法.開(kāi)始我沒(méi)有一點(diǎn)想法,并且沒(méi)有任何技術(shù)數(shù)據(jù)放在我的面前.我開(kāi)始考慮粒子,突然我的腦袋裝滿(mǎn)想法(腦袋開(kāi)啟了??):給予每個(gè)粒子生命,任意變化顏色,速度,重力影響等等.來(lái)適應(yīng)環(huán)境的變化,把每個(gè)粒子看成單一的從這個(gè)點(diǎn)運(yùn)動(dòng)到另一個(gè)點(diǎn)的顆粒.很快我完成了這個(gè)項(xiàng)目.我看看時(shí)鐘然后有個(gè)想法突然出現(xiàn).四個(gè)小時(shí)過(guò)去了!我偶爾記得已經(jīng)停止喝咖啡,眨眼,但是4個(gè)小時(shí)...?盡管這個(gè)程序我覺(jué)得很棒,并象我想象的那么嚴(yán)密的運(yùn)行,但它不可能是最好的粒子引擎,這個(gè)我不關(guān)心,只要他運(yùn)行好就可以.并且我能把它運(yùn)行在我的項(xiàng)目中.如果你是那種想了解透徹的人,那么你要花費(fèi)很多時(shí)間在網(wǎng)絡(luò)上查找資料并弄明白它.在程序中有很多小的代碼會(huì)看起來(lái)很模糊:)本課教程所用的部分代碼來(lái)自于Lesson1.但有很多新的代碼,因此我將重寫(xiě)一些發(fā)生代碼變化的部分(使它更容易了解).
            下面用到的代碼來(lái)自于Lesson6,我將會(huì)增加5行新的代碼在我們程序的前面.第一行"stdio.h"允許我們讀文件中的數(shù)據(jù).它和我們以前用在紋理映射當(dāng)中是一樣的.第二行定義了一些我們要在屏幕上顯示的粒子的數(shù)目.告訴程序MAX_PARTICLES在這里的數(shù)值為1000.第三條行將不斷分離的彩色的粒子栓牢在一起,并設(shè)置為默認(rèn)情況.sp和rp用來(lái)確定空格鍵和返回鍵是否有按住.
             
              

            #define    MAX_PARTICLES    1000        // 定義最大的粒子數(shù)
            bool    rainbow=true;            // 是否為彩虹模式
            bool    sp;                // 空格鍵是否被按下
            bool    rp;                // 回車(chē)鍵是否被按下

              
             下面四行是復(fù)雜的變量.變量slowdown控制粒子移動(dòng)的快慢.數(shù)值愈高,移動(dòng)越慢.數(shù)值越底,移動(dòng)越快.如果數(shù)值降低,粒子將快速的移動(dòng)!粒子的速度影響它們?cè)跓善林幸苿?dòng)的距離.記住速度慢的粒子不會(huì)射很遠(yuǎn)的.變量xspeed和yspeed控制尾部的方向.xspeed將會(huì)增加粒子在x軸上速度.如果xspeed是正值粒子將會(huì)向右邊移動(dòng)多.如果xspeed負(fù)價(jià)值,粒子將會(huì)向左邊移動(dòng)多.那個(gè)值越高,就向那個(gè)方向移動(dòng)比較多.yspeed工作相同的方法,但是在y軸上.因?yàn)橛衅渌囊蛩赜绊懥W拥倪\(yùn)動(dòng),所以我要說(shuō)"多".xspeed和yspeed有助于在我們想要的方向上移動(dòng)粒子.最后是變量zoom,我們用該變量移入或移出我們的屏幕.在粒子引擎里,有時(shí)可看見(jiàn)更多的圖象,而且當(dāng)接近你時(shí)很酷
             
              

            float    slowdown=2.0f;            // 減速粒子
            float    xspeed;                // X方向的速度
            float    yspeed;                // Y方向的速度
            float    zoom=-40.0f;            // 沿Z軸縮放

              
             我們定義了一個(gè)復(fù)雜的循環(huán)變量叫做Loop.我們用這變量預(yù)先定義粒子并在屏幕中畫(huà)粒子.col用來(lái)給予粒子不同的顏色.delay用來(lái)控制在彩虹模式中圓的顏色變化.最后,我們?cè)O(shè)定一個(gè)存儲(chǔ)空間(粒子紋理).我用紋理而不用點(diǎn)的重要原因是,點(diǎn)的速度慢,而且挺麻煩的.其次紋理很酷:)你用一個(gè)正方形的粒子,一張你臉的小圖片,一張星星的圖片等等.很好控制! 
              

            GLuint    loop;                // 循環(huán)變量
            GLuint    col;                // 當(dāng)前的顏色
            GLuint    delay;                // 彩虹效果延遲

              
             好!現(xiàn)在是有趣的東西.下段程序描述單一粒子結(jié)構(gòu),這是我們給予粒子的屬性.我們用布爾型變量active開(kāi)始,如果為true,我們的粒子為活躍的.如果為false則粒子為死的,此時(shí)我們就刪除它.在程序中我沒(méi)有使用活躍的,因?yàn)樗芎玫膶?shí)現(xiàn).變量life和fade來(lái)控制粒子顯示多久以及顯示時(shí)候的亮度.隨著life數(shù)值的降低fade的數(shù)值也相應(yīng)降低.這將導(dǎo)致一些粒子比其他粒子燃燒的時(shí)間長(zhǎng).
             
              

            typedef struct                        // 創(chuàng)建粒子數(shù)據(jù)結(jié)構(gòu)
            {
                bool    active;                    // 是否激活
                float    life;                    // 粒子生命
                float    fade;                    // 衰減速度

              
             變量r,g和b用來(lái)表示粒子的紅色強(qiáng)度,綠色強(qiáng)度和藍(lán)色強(qiáng)度.當(dāng)r的值變成1.0f時(shí)粒子將會(huì)很紅,當(dāng)三個(gè)變量全為1.0f時(shí)則粒子將變成白色.
             
              

                float    r;                    // 紅色值
                float    g;                    // 綠色值
                float    b;                    // 藍(lán)色值

              
             變量x.y和z控制粒子在屏幕上顯示的位置.x表示粒子在x軸上的位置.y表示y軸上的位置.z表示粒子z軸上的位置
             
              

                float    x;                    // X 位置
                float    y;                    // Y 位置
                float    z;                    // Z 位置

              
             下面三個(gè)變量很重要.這三個(gè)變量控制粒子在每個(gè)軸上移動(dòng)的快慢和方向.如果xi是負(fù)價(jià)粒子將會(huì)向左移動(dòng),正值將會(huì)向右移動(dòng).如果yi是負(fù)值粒子將會(huì)向下移動(dòng),正值將向上.最后,如果zi負(fù)值粒子將會(huì)向熒屏內(nèi)部移動(dòng),正植將移向觀察者.  
              

                float    xi;                    // X 方向
                float    yi;                    // Y 方向
                float    zi;                    // Z 方向

              
             最后,另外3個(gè)變量!每一個(gè)變量可被看成加速度.如果xg正值時(shí),粒子將會(huì)被拉倒右邊,負(fù)值將拉向左邊.所以如果粒子向左移動(dòng)(負(fù)的)而我們給它一個(gè)正的加速度,粒子速度將變慢.最后將向反方向移動(dòng)(高中物理).yg拉下或拉上.zg拉進(jìn)或拉出屏幕.
             
              

                float    xg;                    // X 方向重力加速度
                float    yg;                    // Y 方向重力加速度
                float    zg;                    // Z 方向重力加速度

              
             結(jié)構(gòu)的名字為particles. 
              

            }
            particles;                        // 粒子數(shù)據(jù)結(jié)構(gòu)

              
             下面我們創(chuàng)建一個(gè)數(shù)組叫particle.數(shù)組存儲(chǔ)MAX_PARTICLES個(gè)元素.也就是說(shuō)我們創(chuàng)建1000(MAX_PARTICLES)個(gè)粒子,存儲(chǔ)空間為每個(gè)粒子提供相應(yīng)的信息
             
              

            particles particle[MAX_PARTICLES];                // 保存1000個(gè)粒子的數(shù)組

              
             在顏色數(shù)組上我們減少一些代碼來(lái)存儲(chǔ)12中不同的顏色.對(duì)每一個(gè)顏色從0到11我們存儲(chǔ)亮紅,亮綠,和亮藍(lán).下面的顏色表里包含12個(gè)漸變顏色從紅色到紫羅蘭色 
              

            static GLfloat colors[12][3]=                // 彩虹顏色
            {
                {1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
                {0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
                {0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}
            };

              
             這段代碼調(diào)用前面的代碼載入位圖,與前面的代碼相同,只是位圖的名稱(chēng)不同。載入一符名為Particle.bmp的位圖 
              

                if (TextureImage[0]=LoadBMP("Data/Particle.bmp"))    // 載入粒子紋理

              
             窗口改變大小的代碼和前面一樣,不需要改變  
              
              
             我們使用光滑的陰影,清除背景為黑色,關(guān)閉深度測(cè)試,綁定并映射紋理.啟用映射位圖后我們選擇粒子紋理。唯一的改變就是禁用深度測(cè)試和初始化粒子 
              

                glDisable(GL_DEPTH_TEST);                        //禁止深度測(cè)試

              
             下面代碼初始化每個(gè)粒子.我們從活躍的粒子開(kāi)始.如果粒子不活躍,它在熒屏上將不出現(xiàn),無(wú)論它有多少life.當(dāng)我們使粒子活躍之後,我們給它life.我懷疑給粒子生命和顏色漸變的是否是最好的方法,但當(dāng)它運(yùn)行一次后,效果很好!life滿(mǎn)值是1.0f.這也給粒子完整的光亮.
             
              

                for (loop=0;loop<MAX_PARTICLES;loop++)                //初始化所有的粒子
                {
                    particle[loop].active=true;                    // 使所有的粒子為激活狀態(tài)
                    particle[loop].life=1.0f;                    // 所有的粒子生命值為最大

              
             我們通過(guò)給定的值來(lái)設(shè)定粒子退色快慢.每次粒子被拉的時(shí)候life隨著fade而減小.結(jié)束的數(shù)值將是0~99中的任意一個(gè),然后平分1000份來(lái)得到一個(gè)很小的浮點(diǎn)數(shù).最后我們把結(jié)果加上0.003f來(lái)使fade速度值不為0
             
              

                    particle[loop].fade=float(rand()%100)/1000.0f+0.003f;        // 隨機(jī)生成衰減速率

              
             既然粒子是活躍的,而且我們又給它生命,下面將給它顏色數(shù)值.一開(kāi)始,我們就想每個(gè)粒子有不同的顏色.我怎么做才能使每個(gè)粒子與前面顏色箱里的顏色一一對(duì)應(yīng)那?數(shù)學(xué)很簡(jiǎn)單,我們用loop變量乘以箱子中顏色的數(shù)目與粒子最大值(MAX_PARTICLES)的余數(shù).這樣防止最后的顏色數(shù)值大于最大的顏色數(shù)值(12).舉例:900*(12/900)=12.1000*(12/1000)=12,等等
             
              

                    particle[loop].r=colors[loop*(12/MAX_PARTICLES)][0];        // 粒子的紅色顏色
                    particle[loop].g=colors[loop*(12/MAX_PARTICLES)][1];        // 粒子的綠色顏色
                    particle[loop].b=colors[loop*(12/MAX_PARTICLES)][2];        // 粒子的藍(lán)色顏色

              
             現(xiàn)在設(shè)定每個(gè)粒子移動(dòng)的方向和速度.我們通過(guò)將結(jié)果乘于10.0f來(lái)創(chuàng)造開(kāi)始時(shí)的爆炸效果.我們將會(huì)以任意一個(gè)正或負(fù)值結(jié)束.這個(gè)數(shù)值將以任意速度,任意方向移動(dòng)粒子. 
              

                    particle[loop].xi=float((rand()%50)-26.0f)*10.0f;        // 隨機(jī)生成X軸方向速度
                    particle[loop].yi=float((rand()%50)-25.0f)*10.0f;        // 隨機(jī)生成Y軸方向速度
                    particle[loop].zi=float((rand()%50)-25.0f)*10.0f;        // 隨機(jī)生成Z軸方向速度

              
             最后,我們?cè)O(shè)定加速度的數(shù)值.不像一般的加速度僅僅把事物拉下,我們的加速度能拉出,拉下,拉左,拉右,拉前和拉后粒子.開(kāi)始我們需要強(qiáng)大的向下加速度.為了達(dá)到這樣的效果我們將xg設(shè)為0.0f.在x方向沒(méi)有拉力.我們?cè)O(shè)yg為-0.8f來(lái)產(chǎn)生一個(gè)向下的拉力.如果值為正則拉向上.我們不希望粒子拉近或遠(yuǎn)離我們,所以將zg設(shè)為0.0f
             
              

                    particle[loop].xg=0.0f;                        // 設(shè)置X軸方向加速度為0
                    particle[loop].yg=-0.8f;                        //  設(shè)置Y軸方向加速度為-0.8
                    particle[loop].zg=0.0f;                        //  設(shè)置Z軸方向加速度為0
                }

              
             現(xiàn)在為有趣的部分.下面的部分是我們從哪里拉粒子,檢查加速度等等.你要明白它是怎么實(shí)現(xiàn)的,因此仔細(xì)的看:)我們重置Modelview巨陣.在畫(huà)粒子位置的時(shí)候用glVertex3f()命令來(lái)代替tranlations,這樣在我們畫(huà)粒子的時(shí)候不會(huì)改變modelview巨陣
             
              

            int DrawGLScene(GLvoid)                                // 繪制粒子
            {
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                // 以黑色背景清楚
                glLoadIdentity();                                // 重置模型變換矩陣

              
             我們開(kāi)始創(chuàng)建一個(gè)循環(huán)loop.這個(gè)環(huán)將會(huì)更新每一個(gè)粒子.  
              

                for (loop=0;loop<MAX_PARTICLES;loop++)                    // 循環(huán)所有的粒子
                {

              
             首先我們做的事物是檢查粒子是否活躍.如果不活躍,則不被更新.在這個(gè)程序中,它們始終活躍.但是在你自己的程序中,你可能想要使某粒子不活躍  
              

                    if (particle[loop].active)                    // 如果粒子為激活的
                    {

              
             下面三個(gè)變量是我們確定x,y和z位置的暫時(shí)變量.注意:在z的位置上我們加上zoom以便我們的場(chǎng)景在以前的基礎(chǔ)上再移入zoom個(gè)位置.particle[loop].x告訴我們要畫(huà)的x的位置.particle[loop].y告訴我們要畫(huà)的y的位置.particle[loop].z告訴我們要畫(huà)的z的位置     float x=particle[loop].x;                // 返回X軸的位置
                        float y=particle[loop].y;                // 返回Y軸的位置
                        float z=particle[loop].z+zoom;            // 返回Z軸的位置

              
             既然知道粒子位置,就能給粒子上色.particle[loop].r保存粒子的亮紅,particle[loop].g保存粒子的亮綠,particle[loop].b保存粒子的亮藍(lán).注意我用alpha為粒子生命.當(dāng)粒子要燃盡時(shí),它會(huì)越來(lái)越透明直到它最后消失.這就是為什么粒子的生命不應(yīng)該超過(guò)1.0f.如果你想粒子燃燒時(shí)間長(zhǎng),可降低fade減小的速度
             
              

                        // 設(shè)置粒子顏色
                        glColor4f(particle[loop].r,particle[loop].g,particle[loop].b,particle[loop].life);

              
             我們有粒子的位置,并設(shè)置顏色了.所以現(xiàn)在我們來(lái)畫(huà)我們的粒子.我們用一個(gè)三角形帶來(lái)代替一個(gè)四邊形這樣使程序運(yùn)行快一點(diǎn).很多3D card畫(huà)三角形帶比畫(huà)四邊形要快的多.有些3D card將四邊形分成兩個(gè)三角形,而有些不.所以我們按照我們自己的想法來(lái),所以我們來(lái)畫(huà)一個(gè)生動(dòng)的三角形帶
             
              

                        glBegin(GL_TRIANGLE_STRIP);                // 繪制三角形帶

              
              從紅寶書(shū)引述:三角形帶就是畫(huà)一連續(xù)的三角形(三個(gè)邊的多角形)使用vertices V0,V1,V2,然后V2,V1,V3(注意順序),然后V2,V3,V4等等.畫(huà)三角形的順序一樣才能保證三角形帶為相同的表面.要求方向是很重要的,例如:剔除,最少用三點(diǎn)來(lái)畫(huà)當(dāng)?shù)谝粋€(gè)三角形使用vertices0,1和2被畫(huà).如果你看圖片你將會(huì)理解用頂點(diǎn)0,1和2構(gòu)造第一個(gè)三角形(頂端右邊,頂端左邊,底部的右邊).第二個(gè)三角形用點(diǎn)vertices2,1和3構(gòu)造.再一次,如果你注意圖片,點(diǎn)vertices2,1和3構(gòu)造第二個(gè)三角形(底部右邊,頂端左邊,底部左邊).注意:兩個(gè)三角形畫(huà)點(diǎn)順序相同.我看到很多的網(wǎng)站要求第二個(gè)三角形反方向畫(huà).這是不對(duì)的.Opengl從新整理頂點(diǎn)來(lái)保證所有的三角形為同一方向!注意:你在屏幕上看見(jiàn)的三角形個(gè)數(shù)是你敘述的頂點(diǎn)的個(gè)數(shù)減2.在程序中在我們有4個(gè)頂點(diǎn),所以我們看見(jiàn)二個(gè)三角形
             
              

                            glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z);
                            glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z);
                            glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z);
                            glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z);
              
             最后我們告訴Opengl我們畫(huà)完三角形帶
             
              

                        glEnd();

              
             現(xiàn)在我們能移動(dòng)粒子.下面公式可能看起來(lái)很奇怪,其實(shí)很簡(jiǎn)單.首先我們?nèi)〉卯?dāng)前粒子的x位置.然后把x運(yùn)動(dòng)速度加上粒子被減速1000倍后的值.所以如果粒子在x軸(0)上屏幕中心的位置,運(yùn)動(dòng)值(xi)為x軸方向+10(移動(dòng)我們?yōu)橛?,而slowdown等于1,我們移向右邊以10/(1*1000)或 0.01f速度.如果增加slowdown值到2我們只移動(dòng)0.005f.希望能幫助你了解slowdown如何工作.那也是為什么用10.0f乘開(kāi)始值來(lái)叫象素移動(dòng)快速,創(chuàng)造一個(gè)爆發(fā)效果.y和z軸用相同的公式來(lái)計(jì)算附近移動(dòng)粒子
             
              

                        particle[loop].x+=particle[loop].xi/(slowdown*1000);    // 更新X坐標(biāo)的位置
                        particle[loop].y+=particle[loop].yi/(slowdown*1000);    // 更新Y坐標(biāo)的位置
                        particle[loop].z+=particle[loop].zi/(slowdown*1000);    // 更新Z坐標(biāo)的位置

              
             在計(jì)算出下一步粒子移到那里,開(kāi)始考慮重力和阻力.在下面的第一行,將阻力(xg)和移動(dòng)速度(xi)相加.我們的移動(dòng)速度是10和阻力是1.每時(shí)每刻粒子都在抵抗阻力.第二次畫(huà)粒子時(shí),阻力開(kāi)始作用,移動(dòng)速度將會(huì)從10掉到9.第三次畫(huà)粒子時(shí),阻力再一次作用,移動(dòng)速度降低到8.如果粒子燃燒為超過(guò)10次重畫(huà),它將會(huì)最后結(jié)束,并向相反方向移動(dòng).因?yàn)橐苿?dòng)速度會(huì)變成負(fù)值.阻力同樣使用于y和z移動(dòng)速度  
              

                        particle[loop].xi+=particle[loop].xg;            // 更新X軸方向速度大小
                        particle[loop].yi+=particle[loop].yg;            // 更新Y軸方向速度大小
                        particle[loop].zi+=particle[loop].zg;            // 更新Z軸方向速度大小

              
             下行將粒子的生命減少.如果我們不這么做,粒子無(wú)法燒盡.我們用粒子當(dāng)前的life減去當(dāng)前的fade值.每粒子都有不同的fade值,因此他們?nèi)繉?huì)以不同的速度燒盡
             
              

                        particle[loop].life-=particle[loop].fade;        // 減少粒子的生命值

              
             現(xiàn)在我們檢查當(dāng)生命為零的話(huà)粒子是否活著  
              

                        if (particle[loop].life<0.0f)                    // 如果粒子生命值小于0
                        {

              
             如果粒子是小時(shí)(燒盡),我們將會(huì)使它復(fù)原.我們給它全值生命和新的衰弱速度. 
              

                            particle[loop].life=1.0f;                // 產(chǎn)生一個(gè)新的粒子
                            particle[loop].fade=float(rand()%100)/1000.0f+0.003f;    // 隨機(jī)生成衰減速率

              
             我們也重新設(shè)定粒子在屏幕中心放置.我們重新設(shè)定粒子的x,y和z位置為零 
              

                            particle[loop].x=0.0f;                    // 新粒子出現(xiàn)在屏幕的中央
                            particle[loop].y=0.0f;                   
                            particle[loop].z=0.0f;                   
              
             在粒子從新設(shè)置之后,將給它新的移動(dòng)速度/方向.注意:我增加最大和最小值,粒子移動(dòng)速度為從50到60的任意值,但是這次我們沒(méi)將移動(dòng)速度乘10.我們這次不想要一個(gè)爆發(fā)的效果,而要比較慢地移動(dòng)粒子.也注意我把xspeed和x軸移動(dòng)速度相加,y軸移動(dòng)速度和yspeed相加.這個(gè)控制粒子的移動(dòng)方向. 
              

                            particle[loop].xi=xspeed+float((rand()%60)-32.0f);    // 隨機(jī)生成粒子速度
                            particle[loop].yi=yspeed+float((rand()%60)-30.0f);   
                            particle[loop].zi=float((rand()%60)-30.0f);       
              
             最后我們分配粒子一種新的顏色.變量col保存一個(gè)數(shù)字從1到11(12種顏色),我們用這個(gè)變量去找紅,綠,藍(lán)亮度在顏色箱里面.下面第一行表示紅色的強(qiáng)度,數(shù)值保存在colors[col][0].所以如果col是0,紅色的亮度就是1.0f.綠色的和藍(lán)色的值用相同的方法讀取.如果你不了解為什么紅色亮度為1.0f那col就為0.我將一點(diǎn)點(diǎn)的解釋.看著程序的最前面.找到那行:static GLfloat colors[12][3].注意:12行3列.三個(gè)數(shù)字的第一行是紅色強(qiáng)度.第二行是綠色強(qiáng)度而且第三行是藍(lán)色強(qiáng)度.[0],[1]和[2]下面描述的1st,2nd和3rd就是我剛提及的.如果col等于0,我們要看第一個(gè)組.11 是最後一個(gè)組(第12種顏色).
             
              

                            particle[loop].r=colors[col][0];            // 設(shè)置粒子顏色
                            particle[loop].g=colors[col][1];           
                            particle[loop].b=colors[col][2];           
                        }

              
             下行描述加速度的數(shù)值是多少.通過(guò)小鍵盤(pán)8號(hào)鍵,我們?cè)黾觵g(y 地心引力)值.這引起向上的力.如果這個(gè)程序在循環(huán)外面,那么我們必須生成另一個(gè)循環(huán)做相同的工作,因此我們最好放在這里
             
              

                        // 如果小鍵盤(pán)8被按住,增加Y軸方向的加速度
                        if (keys[VK_NUMPAD8] && (particle[loop].yg<1.5f)) particle[loop].yg+=0.01f;

              
             這行是產(chǎn)生相反的效果.通過(guò)2號(hào)鍵,減小yg值,引起向下的力
             
              

                        // 如果小鍵盤(pán)2被按住,減少Y軸方向的加速度
                        if (keys[VK_NUMPAD2] && (particle[loop].yg>-1.5f)) particle[loop].yg-=0.01f;

              
             現(xiàn)在更改向右的拉力.如果按下6號(hào)鍵時(shí)增加向右的拉力.
             
              

                        // 如果小鍵盤(pán)6被按住,增加X(jué)軸方向的加速度
                        if (keys[VK_NUMPAD6] && (particle[loop].xg<1.5f)) particle[loop].xg+=0.01f;

              
             最后如果4號(hào)鍵被按下則增加向左的拉力.這些按鍵給了我們很酷的結(jié)果.舉例來(lái)說(shuō):你可以用粒子造一條向上設(shè)的水流.通過(guò)增加向下的引力可以形成泉水
             
              

                        // 如果小鍵盤(pán)4被按住,減少X軸方向的加速度
                        if (keys[VK_NUMPAD4] && (particle[loop].xg>-1.5f)) particle[loop].xg-=0.01f;

              
             我僅僅為樂(lè)趣增加了一些代碼.我的兄弟產(chǎn)生很棒的效果:)通過(guò)按住tab鍵所有粒子都回到屏幕中心.所有的粒子在從新開(kāi)始運(yùn)動(dòng),再產(chǎn)生一個(gè)大的爆發(fā).在粒子變?nèi)踔?你最初的效果會(huì)再一次出現(xiàn)
             
              

                        if (keys[VK_TAB])                        // 按Tab鍵,使粒子回到原點(diǎn)
                        {
                            particle[loop].x=0.0f;                   
                            particle[loop].y=0.0f;                   
                            particle[loop].z=0.0f;                   
                            particle[loop].xi=float((rand()%50)-26.0f)*10.0f;    // 隨機(jī)生成速度
                            particle[loop].yi=float((rand()%50)-25.0f)*10.0f;   
                            particle[loop].zi=float((rand()%50)-25.0f)*10.0f;   
                        }
                    }
                }
                return TRUE;                                    // 繪制完畢成功返回
            }

              
             代碼KillGLWindow(),CreateGLWindow()和WndProc()中沒(méi)有改變,所以我們直接跳到WinMain().我將重寫(xiě)代碼 
              
              
             我喜歡簡(jiǎn)單的代碼.在一行上不想包含很多東西,所以使代碼象一個(gè)清潔工:)下面的代碼檢查"+"是否被按下.如果它和slowdown一起實(shí)現(xiàn)則slowdown減少0.01f.粒子就可以較快速地移動(dòng).
             
              

                            if (keys[VK_ADD] && (slowdown>1.0f)) slowdown-=0.01f;        // 按+號(hào),加速粒子

              
             下面的代碼檢查"-"是否被按下.如果它和slowdown一起實(shí)現(xiàn)則slowdown增加0.01f.粒子就可以較慢速地移動(dòng).我實(shí)質(zhì)的極限是4.0f,我不想它太慢的運(yùn)動(dòng),你可以隨你的要求改變最大最小值 
              

                            if (keys[VK_SUBTRACT] && (slowdown<4.0f)) slowdown+=0.01f;    // 按-號(hào),減速粒子

              
             下面的代碼檢測(cè)Page Up是否被按下.如果是,則zoom增加.從而導(dǎo)致粒子靠近我們 
              

                            if (keys[VK_PRIOR]) zoom+=0.1f;        // 按Page Up鍵,讓粒子靠近視點(diǎn)

              
             下行代碼檢測(cè)Page Down是否別按下,如果是,則zoom減小.從而導(dǎo)師粒子離開(kāi)我們
             
              

                            if (keys[VK_NEXT]) zoom-=0.1f;        // 按Page Down,讓粒子遠(yuǎn)離視點(diǎn)

              
             下面的代碼檢驗(yàn)enter鍵是否被按下.如果是,并且沒(méi)有被一直按著,我們將讓計(jì)算機(jī)把rp變?yōu)閠rue,然后我們固定彩虹模式.如果彩虹模式為true,將其變成false.如果為false,將其變成true.最后一行檢測(cè)enter是否被釋放,如果釋放rp為false并告訴計(jì)算機(jī)該鍵不被按下
             
              

                            if (keys[VK_RETURN] && !rp)        // 按住回車(chē)鍵,切換彩虹模式
                            {
                                rp=true;           
                                rainbow=!rainbow;       
                            }
                            if (!keys[VK_RETURN]) rp=false;       
              
             下面程序有點(diǎn)亂.第一行檢查space鍵是否被按下并沒(méi)有沒(méi)一直按著.并檢查彩虹模式是否開(kāi)始運(yùn)行,如果是,檢查delay是否大于25.delay是我創(chuàng)建的顯示彩虹效果的數(shù)值.如果你曾經(jīng)改變顏色結(jié)構(gòu),粒子將顯示不同顏色.通過(guò)創(chuàng)建一個(gè)delay,在顏色改變之前,一組粒子將是一種顏色.如果space按下,彩虹運(yùn)行,delay值大于25則顏色改變
             
              

                            if ((keys[' '] && !sp) || (rainbow && (delay>25)))    // 空格鍵,變換顏色
                            {

              
             下面行是為了當(dāng)space按下則彩虹關(guān)掉而設(shè)置的.如果我們不關(guān)掉彩虹模式,顏色會(huì)繼續(xù)變化直到enter再被按下.也就是說(shuō)人們按下space來(lái)代替enter是想叫粒子顏色自己變化 
              

                                if (keys[' ']) rainbow=false;   

              
             如果space鍵被按下,或者彩虹模式已開(kāi)始,并且delay大于25,我們叫計(jì)算機(jī)知道space鍵被按下通過(guò)叫sp為true.然后我們將delay設(shè)定回0以便它能在到25.最后我們?cè)黾觕ol的值以便它通過(guò)顏色箱里面改變成另一個(gè)顏色. 
              

                                sp=true;           
                                delay=0;           
                                col++;               
              
             如果顏色值大于11,我們把它重新設(shè)為零.如果我們不重新設(shè)定為零,程序?qū)⑷フ业?3顏色.而我們只有12種顏色!尋找不存在的顏色將會(huì)導(dǎo)致程序癱瘓 
              

                                if (col>11) col=0;
                            }

              
             最后如果space鍵不被按下,我們將sp設(shè)為false。 
              

                            if (!keys[' '])    sp=false;        // 如果釋放空格鍵,記錄這個(gè)狀態(tài)

              
             現(xiàn)在對(duì)粒子增加一些控制.還記得我們從開(kāi)始定義的2變量么?一個(gè)xspeed,一個(gè)yspeed.在粒子燃盡之后,我們給它新的移動(dòng)速度且把新的速度加入到xspeed和yspeed中.這樣當(dāng)粒子被創(chuàng)建時(shí)將影響粒子的速度. 舉例來(lái)說(shuō):粒子在x軸上的速度為5在y軸上的速度為0.當(dāng)我們減少xspeed到-10,我們將以-10(xspeed)+5(最初的移動(dòng)速度)的速度移動(dòng).這樣我們將以5的速度向左移動(dòng).明白了么??無(wú)論如何,下面的代碼檢測(cè)UP是否被按下.如果它,yspeed將增加這將引起粒子向上運(yùn)動(dòng).最大速度不超過(guò)200.速度在快就不好看了
             
              

                            // 按上增加粒子Y軸正方向的速度
                            if (keys[VK_UP] && (yspeed<200)) yspeed+=1.0f;

              
             這行檢查Down鍵是否被按下,如果它是,yspeed將減少.這將引起粒子向下運(yùn)動(dòng).再一次,最大速度為200 
              

                            // 按下減少粒子Y軸正方向的速度
                            if (keys[VK_DOWN] && (yspeed>-200)) yspeed-=1.0f;

              
             現(xiàn)在我們檢查Right鍵是否被按下.如果它是..xspeed將被增加.粒子將移到右邊.最大速度為200 
              

                            // 按右增加粒子X(jué)軸正方向的速度
                            if (keys[VK_RIGHT] && (xspeed<200)) xspeed+=1.0f;

              
             最后我們檢查L(zhǎng)eft鍵是否被按下.如果是...你猜....xspeed被減小,粒子開(kāi)始向左移動(dòng).最大速度為200 
              

                            // 按左減少粒子X(jué)軸正方向的速度
                            if (keys[VK_LEFT] && (xspeed>-200)) xspeed-=1.0f;

              
             最后我們要增加delay的數(shù)值.像我在前面所說(shuō),delay是控制彩色變化的 
              

                            delay++;            // 增加彩虹模式的顏色切換延遲

              
             在課程中,我試著把所有細(xì)節(jié)都講清楚,并且簡(jiǎn)單的了解粒子系統(tǒng).這個(gè)粒子系統(tǒng)能在游戲產(chǎn)生例如火,水,雪,爆炸,流行等效果.程序能簡(jiǎn)單的修改參數(shù)來(lái)實(shí)現(xiàn)新的效果(例:煙花效果)
             
             


            posted on 2007-12-16 14:27 sdfasdf 閱讀(4599) 評(píng)論(2)  編輯 收藏 引用 所屬分類(lèi): OPENGL

            Feedback

            # re: NEHE的OPENGL教程 第十九課 粒子系統(tǒng) 2007-12-17 09:04 學(xué)海一人
            ding  回復(fù)  更多評(píng)論
              

            # re: NEHE的OPENGL教程 第十九課 粒子系統(tǒng) 2007-12-17 09:06 美妹
            謝謝  回復(fù)  更多評(píng)論
              

            久久99免费视频| 亚洲а∨天堂久久精品9966| 久久久免费精品re6| 99久久精品国产麻豆| 久久国产精品免费| 久久久无码精品亚洲日韩京东传媒| 久久精品国产亚洲av麻豆图片| 精品乱码久久久久久久| 免费一级欧美大片久久网| 久久国产精品无码HDAV| 亚洲人成无码网站久久99热国产 | 久久AV无码精品人妻糸列| 欧美熟妇另类久久久久久不卡| 久久综合狠狠色综合伊人| 久久久无码精品亚洲日韩蜜臀浪潮 | 色妞色综合久久夜夜| 97精品伊人久久大香线蕉app| 久久无码一区二区三区少妇| 国产精品久久精品| 麻豆一区二区99久久久久| 久久综合九色综合欧美就去吻| 久久国产精品国产自线拍免费| 久久综合亚洲欧美成人| 欧美激情一区二区久久久| 精品久久久久中文字幕一区| 热久久这里只有精品| 天天躁日日躁狠狠久久| 中文字幕久久久久人妻| 亚洲AV日韩精品久久久久久久| 亚洲欧美一区二区三区久久| 国产精品免费久久久久久久久 | 亚洲va国产va天堂va久久| 亚洲人成无码久久电影网站| 香港aa三级久久三级老师2021国产三级精品三级在 | 久久99久久99精品免视看动漫| 久久精品一本到99热免费| 亚洲婷婷国产精品电影人久久 | 久久免费高清视频| 国产女人aaa级久久久级| 国产高潮国产高潮久久久91 | 亚洲欧美日韩精品久久亚洲区 |