• <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 逛奔的蝸牛 閱讀(2855) 評論(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咋辦?謝謝。  回復  更多評論
              

            精品乱码久久久久久久| 久久无码专区国产精品发布 | 久久国产影院| 久久精品国产亚洲Aⅴ蜜臀色欲| 久久高潮一级毛片免费| 亚洲va中文字幕无码久久不卡| 69SEX久久精品国产麻豆| 久久99精品久久久久久9蜜桃 | 精品国产91久久久久久久a| 久久天天躁狠狠躁夜夜av浪潮 | 国产日韩久久久精品影院首页| 四虎久久影院| 99久久综合狠狠综合久久| 无码人妻精品一区二区三区久久久| 久久综合九色综合精品| 伊人色综合久久天天人手人婷| 天天爽天天爽天天片a久久网| 久久婷婷色香五月综合激情| 久久se精品一区精品二区| 怡红院日本一道日本久久| 久久青青草视频| 久久人搡人人玩人妻精品首页| 996久久国产精品线观看| 国内精品九九久久精品| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 国产A级毛片久久久精品毛片| 日韩精品无码久久久久久| 久久综合偷偷噜噜噜色| 狠狠综合久久综合中文88| 蜜桃麻豆www久久| 久久精品国产精品青草app| 久久国产亚洲精品无码| 久久午夜无码鲁丝片| 亚洲国产精品久久久天堂| 欧美va久久久噜噜噜久久| 国内精品人妻无码久久久影院导航| 一个色综合久久| 久久午夜无码鲁丝片| 国内精品久久九九国产精品| 国产精品天天影视久久综合网| 精品久久无码中文字幕|