進一步使用 模板緩沖(stencil)


  

  最近做課題的時候需要計算一個 view(就是一次渲染得到的幀) 下的重疊像素個數(兩個物體或更多的物體重疊)。

  • 最開始我的想法是渲染一個物體輸出一張紋理,這樣對比物體之間的紋理就知道重疊了。但是這樣當物體很多的時候需要輸出太多的紋理到CPU,太慢了,也很麻煩。
  • 后來和同學討論了一下,覺得是不是可以使用一張紋理作為幀緩沖的輸出,同時作為片段着色器的輸入,這樣可以每渲染一個像素點加1,最終大於1的位置表示重疊。但是后來這樣試了,在片段着色器中采樣這張紋理的時候,采樣出來的值明顯不對,沒有隨着渲染一個物體后再次采樣會逐步積累增加。(感覺因為是同一張紋理,但是是輸入和輸出,在GPU中分配了兩個存儲位置,各自使用自己的,所以沒有疊加,我瞎猜的……)
  • 后來查到仿佛可以使用累積緩沖,每次渲染的結果疊加在一起,但是需要加權,value = α*value + (1-α)*newvalue ,感覺不太好操作,放棄了。
  • 最后看了一下stencil,發現可以實現我需要的功能。雖然幾個月前看過一次,但是當時沒有太懂,這次算是理解了。

  

  現在再來回顧一下 Stencil 的用法:

  • glStencilMask(value) 位遮罩, value=0x00表示模板緩沖不可寫入;value=0xFF表示可以寫入。
  • void glStencilFunc(GLenum func, GLint ref, GLuint mask)  指定ref值與存儲的模板值對比
  • void glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) 指定模板值的寫入策略

  

  流程代碼

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_STENCIL_TEST);
        glStencilMask(0xFF); //開啟模板寫入 (清空模板緩沖需要開啟模板寫入!!!)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // 我們現在使用模板緩沖
        glStencilOp(GL_INCR, GL_INCR, GL_INCR);
        glStencilMask(0x00); //關閉模板寫入
        this->DrawSkyBox(false);
        this->DrawFloor(false);
        glStencilFunc(GL_ALWAYS, 1, 0xFF);
        glStencilMask(0xFF); //開啟模板寫入
        this->DrawBuildings(false);  // 先渲染building,shader中的編號保持一致,但是sky一定在前
        glStencilMask(0x00); //關閉模板寫入

  遇到的坑是清空模板緩沖前一定要開啟模板寫入!!!

 

  模板值讀取:

    這個耽擱了很久,開始是附加模板紋理到幀緩沖中,然后從紋理中讀取值,但是怎么都讀出來不對……

    后來發現可以直接使用其API讀取   glReadPixels 。

    使用此API讀取時,其是直接面向當前幀緩沖獲取模板值數據,故與模板生成方式無關,可以是默認屏幕的幀緩沖,也可以使自己生成的幀緩沖(可以是RBO模板緩沖、模板緩沖紋理、深度-模板緩沖紋理)。

float* WKS::Texture::GetStencilData(GLuint width, GLuint height) {
    float* pixels = new float[width * height];
    glReadPixels(0, 0, width, height, GL_STENCIL_INDEX, GL_FLOAT, pixels);
    return pixels;
}

  一定要記得在對應的幀緩沖中使用。

 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM