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

            逛奔的蝸牛

            我不聰明,但我會很努力

               ::  :: 新隨筆 ::  ::  :: 管理 ::
            每個像素都有自己對應的 Buffer,其實就是一個 32bit 的數,如 Color Buffer, Depth Buffer, Stencil Buffer. Stencil Buffer 與 Depth Buffer 有點特別,因為他們共用同一個 Buffer, Depth Buffer 占用 Buffer 前面的 24Bit, Stencil Buffer 占用后面的 8Bit. Stencil Buffer 可以使用從 1Bit-8Bit. 如在繪制反射時,就像照鏡子一樣,因為只需要在反射平面上繪制物體的鏡像,即要么在反射平面上繪制,要不就不繪制,所以只需要用到 1Bit 的 Stencil Buffer.
             
            什么叫 Stencil Buffer ?
            即是一個模板,也就是說,他可以是一個平面,也可以是一個立體幾何圖形,如一個四邊形,一個Teapot. 在模板所占據的空間中,他的值為 1(values stored in the stencil buffer), 在啟用 Stencil Buffer 時,我們所畫的圖形只有在這個空間中的部分才能顯示出來,所以我們可以創建一個模板,他是一個字,然后以后畫的圖形最多只能把這個字給顯示出來,這個圖形有其他部分都沒有被寫進 Color Buffer.
             
            Stencil Buffer 最簡單的運用,用來生成鏡面反射。
            1. 先要使編程環境支持 Stencil Buffer
                    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
             
            2. 設置清除 Stencil Buffer 使用的函數
                    glClearStencil(0);
             
            3. 在我們創建模板的時候,要先關掉 Depth Test und Color Mask,
                    因為我們并不想把模板畫到屏幕上
                    glDisable(GL_DEPTH_TEST);
                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                    // 為了把我們的模板圖形不顯示到屏幕上,但又要寫入 Stencil Buffer 中。
             
                    我們什么時候創建模板的?就是在啟用模板緩存后進行的第一次進繪制的圖形就是模板。
                    OpenGL會根據我們所設定的 glStencilFunc 的值和 glStencilOp 來比較,
                    然后在 plane 中(即視口所對應的那個二維數組)寫入比較的結果值。
             
            4. 開始創建模板
                    glEnable(GL_STENCIL_TEST);
                    glStencilFunc(GL_ALWAYS, 0x1, 0x1);
                    // 把模板圖形所在的區域的 Buffer 值設置成 1, 其余的還是 0.
                    // 這時用的就是給 glStencilFunc 指定的 ref 的值,現在是 1
                    // 當然可以有其他的操作,如 GL_INCR, GL_INVERT(bitwise invert)
                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
                   
                    // 開始創建模板的圖形
                    drawFloor();
                   
                    // 模板創建好后,我們就要設置下一次進行繪制時的模板函數
                    // 只有通過條件的像素才能被顯示到屏幕上,否則就被丟棄
                    // 但要注意,現在我們要進行繪制的就是鏡像了,所以是要被顯示到屏幕上的,
                    // 所以在繪制之前,要把顏色屏蔽關掉和啟用深度測試
                    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. 繪制鏡像圖像
                    // 現在繪制我們的鏡像圖像
                    // 鏡像是跟原來的物體對稱的, 所以用 glScalef 來進行反轉,實現對稱
                    // 在繪制鏡像物體的時候,燈光也要相應的反轉
                    glPushMatrix();
                            glScalef(1, -1, 1);
                            glutSolidTeapot(1.0f);
                    glPopMatrix();
             
            6. 在模板中顯示的鏡像圖像已經創建好,不再需要模板了,所以我們關掉 stencil buffer
                    glDisable(GL_STENCIL_TEST);
             
            7. 繪制鏡像所在的平面,就如鏡子
                    // 使用 Blend 與鏡像圖像混合起來
                    glEnable(GL_BLEND);
                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                    drawFloor();
                    glDisable(GL_BLEND);
             
            8. 繪制產生鏡像的物體
                    glutSolidTeapot(1.0f);
             
            至此,真正的鏡面反射已經創建完成。
            非真正的反射可以如下實現:
            先畫對稱物體,畫出鏡面(使用 Blend), 然后畫出原物體,但這時如果旋轉Camera,就會發現,那個對稱的物體并不是平面的,還是原來的空間立體物體。但用 Stencil Buffer 實現的鏡面反射是真正的鏡面反射,鏡像是只在鏡面上顯示,即是平面的。
             
            下面的代碼可以很好的工作
             //****************************************************************//
             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 逛奔的蝸牛 閱讀(2859) 評論(4)  編輯 收藏 引用 所屬分類: OpenGL

            評論

            # re: OpenG:Reflection-Stencil Buffer[未登錄] 2013-09-16 16:15 james
            博主,你這個字體顏色著實讓人開的眼睛很疼。  回復  更多評論
              

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

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

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

            色综合久久中文字幕无码| 久久久青草久久久青草| 久久久久综合国产欧美一区二区| 精品久久久久久国产91| 国产女人aaa级久久久级| 久久久久亚洲?V成人无码| 国内精品综合久久久40p| 国产韩国精品一区二区三区久久| 久久久久久久综合综合狠狠| 久久精品国产精品亚洲精品| 国产精品美女久久久久av爽| 区久久AAA片69亚洲| 99精品久久精品| 亚洲七七久久精品中文国产 | 国产日产久久高清欧美一区| 国产一区二区精品久久| 久久久久久久精品成人热色戒| 精品久久久久久综合日本| 久久无码专区国产精品发布| 91超碰碰碰碰久久久久久综合| 国产精品久久久久a影院| 99久久国产综合精品成人影院| 色综合久久久久无码专区| 久久久久亚洲爆乳少妇无| 久久综合给久久狠狠97色| 久久亚洲AV无码精品色午夜麻豆| 93精91精品国产综合久久香蕉| 久久综合狠狠综合久久综合88| 久久精品中文字幕一区| 亚洲午夜无码AV毛片久久| 久久人人爽人人爽人人片AV麻豆 | 国内精品久久国产| 国产精品无码久久综合网| 国产AV影片久久久久久| 丰满少妇高潮惨叫久久久| 97热久久免费频精品99| 色诱久久久久综合网ywww| 性欧美大战久久久久久久久| 色欲久久久天天天综合网| 国产精品一区二区久久不卡 | 久久男人AV资源网站|