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

  

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

  • 最開始個人想法是渲染一個物體輸出一張紋理,這樣對比物體之間的紋理就知道重疊了。可是這樣當物體不少的時候須要輸出太多的紋理到CPU,太慢了,也很麻煩。
  • 後來和同窗討論了一下,以爲是否是可使用一張紋理做爲幀緩衝的輸出,同時做爲片斷着色器的輸入,這樣能夠每渲染一個像素點加1,最終大於1的位置表示重疊。可是後來這樣試了,在片斷着色器中採樣這張紋理的時候,採樣出來的值明顯不對,沒有隨着渲染一個物體後再次採樣會逐步積累增長。(感受由於是同一張紋理,可是是輸入和輸出,在GPU中分配了兩個存儲位置,各自使用本身的,因此沒有疊加,我瞎猜的……)
  • 後來查到彷彿可使用累積緩衝,每次渲染的結果疊加在一塊兒,可是須要加權,value = α*value + (1-α)*newvalue ,感受不太好操做,放棄了。
  • 最後看了一下stencil,發現能夠實現我須要的功能。雖然幾個月前看過一次,可是當時沒有太懂,此次算是理解了。

  

  如今再來回顧一下 Stencil 的用法:this

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

  

  流程代碼spa

        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); //關閉模板寫入

  遇到的坑是清空模板緩衝前必定要開啓模板寫入!!!code

 

  模板值讀取:blog

    這個耽擱了好久,開始是附加模板紋理到幀緩衝中,而後從紋理中讀取值,可是怎麼都讀出來不對……ci

    後來發現能夠直接使用其API讀取   glReadPixels 。模板

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

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;
}

  必定要記得在對應的幀緩衝中使用。渲染

相關文章
相關標籤/搜索