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

            逛奔的蝸牛

            我不聰明,但我會(huì)很努力

               ::  :: 新隨筆 ::  ::  :: 管理 ::
            每個(gè)像素都有自己對(duì)應(yīng)的 Buffer,其實(shí)就是一個(gè) 32bit 的數(shù),如 Color Buffer, Depth Buffer, Stencil Buffer. Stencil Buffer 與 Depth Buffer 有點(diǎn)特別,因?yàn)樗麄児灿猛粋€(gè) Buffer, Depth Buffer 占用 Buffer 前面的 24Bit, Stencil Buffer 占用后面的 8Bit. Stencil Buffer 可以使用從 1Bit-8Bit. 如在繪制反射時(shí),就像照鏡子一樣,因?yàn)橹恍枰诜瓷淦矫嫔侠L制物體的鏡像,即要么在反射平面上繪制,要不就不繪制,所以只需要用到 1Bit 的 Stencil Buffer.
             
            什么叫 Stencil Buffer ?
            即是一個(gè)模板,也就是說(shuō),他可以是一個(gè)平面,也可以是一個(gè)立體幾何圖形,如一個(gè)四邊形,一個(gè)Teapot. 在模板所占據(jù)的空間中,他的值為 1(values stored in the stencil buffer), 在啟用 Stencil Buffer 時(shí),我們所畫(huà)的圖形只有在這個(gè)空間中的部分才能顯示出來(lái),所以我們可以創(chuàng)建一個(gè)模板,他是一個(gè)字,然后以后畫(huà)的圖形最多只能把這個(gè)字給顯示出來(lái),這個(gè)圖形有其他部分都沒(méi)有被寫(xiě)進(jìn) Color Buffer.
             
            Stencil Buffer 最簡(jiǎn)單的運(yùn)用,用來(lái)生成鏡面反射。
            1. 先要使編程環(huán)境支持 Stencil Buffer
                    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
             
            2. 設(shè)置清除 Stencil Buffer 使用的函數(shù)
                    glClearStencil(0);
             
            3. 在我們創(chuàng)建模板的時(shí)候,要先關(guān)掉 Depth Test und Color Mask,
                    因?yàn)槲覀儾⒉幌氚涯0瀹?huà)到屏幕上
                    glDisable(GL_DEPTH_TEST);
                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                    // 為了把我們的模板圖形不顯示到屏幕上,但又要寫(xiě)入 Stencil Buffer 中。
             
                    我們什么時(shí)候創(chuàng)建模板的?就是在啟用模板緩存后進(jìn)行的第一次進(jìn)繪制的圖形就是模板。
                    OpenGL會(huì)根據(jù)我們所設(shè)定的 glStencilFunc 的值和 glStencilOp 來(lái)比較,
                    然后在 plane 中(即視口所對(duì)應(yīng)的那個(gè)二維數(shù)組)寫(xiě)入比較的結(jié)果值。
             
            4. 開(kāi)始創(chuàng)建模板
                    glEnable(GL_STENCIL_TEST);
                    glStencilFunc(GL_ALWAYS, 0x1, 0x1);
                    // 把模板圖形所在的區(qū)域的 Buffer 值設(shè)置成 1, 其余的還是 0.
                    // 這時(shí)用的就是給 glStencilFunc 指定的 ref 的值,現(xiàn)在是 1
                    // 當(dāng)然可以有其他的操作,如 GL_INCR, GL_INVERT(bitwise invert)
                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
                   
                    // 開(kāi)始創(chuàng)建模板的圖形
                    drawFloor();
                   
                    // 模板創(chuàng)建好后,我們就要設(shè)置下一次進(jìn)行繪制時(shí)的模板函數(shù)
                    // 只有通過(guò)條件的像素才能被顯示到屏幕上,否則就被丟棄
                    // 但要注意,現(xiàn)在我們要進(jìn)行繪制的就是鏡像了,所以是要被顯示到屏幕上的,
                    // 所以在繪制之前,要把顏色屏蔽關(guān)掉和啟用深度測(cè)試
                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
                    glEnable(GL_DEPTH_TEST);
             
                    // Stencil buffer 值等于 1 的地方才繪制到屏幕上       
                    glStencilFunc(GL_EQUAL, 0x1, 0x1);
                    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
             
            5. 繪制鏡像圖像
                    // 現(xiàn)在繪制我們的鏡像圖像
                    // 鏡像是跟原來(lái)的物體對(duì)稱(chēng)的, 所以用 glScalef 來(lái)進(jìn)行反轉(zhuǎn),實(shí)現(xiàn)對(duì)稱(chēng)
                    // 在繪制鏡像物體的時(shí)候,燈光也要相應(yīng)的反轉(zhuǎn)
                    glPushMatrix();
                            glScalef(1, -1, 1);
                            glutSolidTeapot(1.0f);
                    glPopMatrix();
             
            6. 在模板中顯示的鏡像圖像已經(jīng)創(chuàng)建好,不再需要模板了,所以我們關(guān)掉 stencil buffer
                    glDisable(GL_STENCIL_TEST);
             
            7. 繪制鏡像所在的平面,就如鏡子
                    // 使用 Blend 與鏡像圖像混合起來(lái)
                    glEnable(GL_BLEND);
                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                    drawFloor();
                    glDisable(GL_BLEND);
             
            8. 繪制產(chǎn)生鏡像的物體
                    glutSolidTeapot(1.0f);
             
            至此,真正的鏡面反射已經(jīng)創(chuàng)建完成。
            非真正的反射可以如下實(shí)現(xiàn):
            先畫(huà)對(duì)稱(chēng)物體,畫(huà)出鏡面(使用 Blend), 然后畫(huà)出原物體,但這時(shí)如果旋轉(zhuǎn)Camera,就會(huì)發(fā)現(xiàn),那個(gè)對(duì)稱(chēng)的物體并不是平面的,還是原來(lái)的空間立體物體。但用 Stencil Buffer 實(shí)現(xiàn)的鏡面反射是真正的鏡面反射,鏡像是只在鏡面上顯示,即是平面的。
             
            下面的代碼可以很好的工作
             //****************************************************************//
             if (useStencil) {
                      glClearStencil(0);
                      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
             } else {
                      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             }

             if (useStencil) {
                      glDisable(GL_DEPTH_TEST);
                      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                      /* Draw 1 into the stencil buffer. */
                      glEnable(GL_STENCIL_TEST);
                      glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
                      glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
                      /* Now render floor; floor pixels just get their stencil set to 1. */
                      drawFloor();
                      /* Re-enable update of color and depth. */
                      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
                      glEnable(GL_DEPTH_TEST);
                      /* Now, only render where stencil is set to 1. */
                      glStencilFunc(GL_EQUAL, 1, 0xffffffff); /* draw if ==1 */
                      glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
             }
             glPushMatrix();
                      glScalef(1, -1, 1);
                      glTranslatef(0.0, 0.8, 0);
                      glColor3f(0, 1, 0);
                      glutSolidTeapot(1);
             glPopMatrix();
             
             if (useStencil) {
                      glDisable(GL_STENCIL_TEST);
             }
             glEnable(GL_BLEND);
             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
             glColor4f(0.7, 0.0, 0.0, 0.3);
             drawFloor();
             glDisable(GL_BLEND);
             
             glTranslatef(0, -0.0001, 0);
             glFrontFace(GL_CW);
             glColor3f(1, 1, 1);
             drawFloor();
             
             glTranslatef(0.0, 0.8, 0);
             glColor3f(0, 1, 0);
             glutSolidTeapot(1);
             //****************************************************************//
             
            posted on 2010-12-17 17:39 逛奔的蝸牛 閱讀(2867) 評(píng)論(4)  編輯 收藏 引用 所屬分類(lèi): OpenGL

            評(píng)論

            # re: OpenG:Reflection-Stencil Buffer[未登錄](méi) 2013-09-16 16:15 james
            博主,你這個(gè)字體顏色著實(shí)讓人開(kāi)的眼睛很疼。  回復(fù)  更多評(píng)論
              

            # re: OpenG:Reflection-Stencil Buffer 2014-05-01 10:32 tutu
            博主,你這個(gè)字體顏色著實(shí)讓人看的眼睛很疼。  回復(fù)  更多評(píng)論
              

            # re: OpenG:Reflection-Stencil Buffer 2015-09-10 10:05 f
            博主,你這個(gè)字體顏色著實(shí)讓人看的眼睛很疼。  回復(fù)  更多評(píng)論
              

            # re: OpenG:Reflection-Stencil Buffer 2016-04-20 21:15 一顆賽艇
            那若是反射面不是y=0平面,而是任意ax+by+cz=d咋辦?謝謝。  回復(fù)  更多評(píng)論
              

            91精品国产高清久久久久久io| 伊人久久成人成综合网222| 99久久人妻无码精品系列蜜桃| 欧美大香线蕉线伊人久久| 国产精品久久久久久一区二区三区| 久久青青草原国产精品免费| 中文精品99久久国产 | 欧洲国产伦久久久久久久| 久久精品无码免费不卡| 性做久久久久久免费观看| 国内精品综合久久久40p| 久久精品亚洲欧美日韩久久| 久久综合九色综合网站| 开心久久婷婷综合中文字幕| 久久精品国产亚洲av麻豆小说 | 久久久艹| 国产成人香蕉久久久久| 99国产欧美精品久久久蜜芽| 欧美亚洲国产精品久久久久| 麻豆久久久9性大片| 久久夜色tv网站| 久久成人精品| 久久人人爽人人精品视频 | 26uuu久久五月天| 久久99精品久久久久婷婷| 国产91色综合久久免费分享| 国产精品无码久久综合| 久久ZYZ资源站无码中文动漫| 午夜久久久久久禁播电影| 久久夜色精品国产欧美乱| 久久亚洲精品国产精品| 成人久久综合网| 99久久国产综合精品五月天喷水| 久久久久免费视频| 亚洲国产日韩欧美综合久久| 久久亚洲高清综合| 久久人人爽人人爽人人AV东京热 | 精品久久久久一区二区三区| 久久久久无码专区亚洲av| 亚洲欧美日韩中文久久| 久久国产精品久久|