日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenGL超级宝典笔记——遮挡查询 [转]

發布時間:2024/4/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGL超级宝典笔记——遮挡查询 [转] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄[-]

  • 遮擋查詢之前
  • 包圍體
  • 遮擋查詢

在一個場景中,如果有有些物體被其他物體遮住了不可見。那么我們就不需要繪制它。在復雜的場景中,這可以減少大量的頂點和像素的處理,大幅度的提高幀率。遮擋查詢就是允許我們判斷一組圖形在進行了深度測試之后是否可見。

遮擋查詢之前

為了顯示遮擋查詢對性能的提升,我們需要一個對照組(不使用遮擋查詢來渲染場景)。

首先我們先繪制“主遮擋物”。這個主遮擋物不需要太多的細節,一般是墻,天花板,地板之類的物體。在下面的例子中我們,使用6面墻來組成這個主遮擋物。

void?DrawOccluder() {glColor3f(0.5f,?0.25f,?0.0f);glPushMatrix();glScalef(30.0f,?30.0f,?1.0f);glTranslatef(0.0f,?0.0f,?50.0f);glutSolidCube(10.0f);glTranslatef(0.0f,?0.0f,?-100.0f);glutSolidCube(10.0f);glPopMatrix();glPushMatrix();glScalef(1.0f,?30.0f,?30.0f);glTranslatef(50.0f,?0.0f,?0.0f);glutSolidCube(10.0f);glTranslatef(-100.0f,?0.0f,?0.0f);glutSolidCube(10.0f);glPopMatrix();glPushMatrix();glScalef(30.0f,?1.0f,?30.0f);glTranslatef(0.0f,?50.0f,?0.0f);glutSolidCube(10.0f);glTranslatef(0.0f,?-100.0f,?0.0f);glutSolidCube(10.0f);glPopMatrix(); }

現在我們在每一個單元格中,放置一個高度分挌化的紋理球體。這些球體可能是被遮擋物,也可能是遮擋物。

void?DrawSphere(GLint?sphereNum)? {?...glutSolidSphere(50.0f,?200,?200);? ...}void?DrawModels(void)? {?//開啟紋理?自動生成紋理坐標glEnable(GL_TEXTURE_2D);?glEnable(GL_TEXTURE_GEN_S);?glEnable(GL_TEXTURE_GEN_T);?//繪制27個不同顏色的球體for?(r?=?0;?r?<?3;?r++)?{?for?(g?=?0;?g?<?3;?g++)?{?for?(b?=?0;?b?<?3;?b++)?{?glColor3f(r?*?0.5f,?g?*?0.5f,?b?*?0.5f);?glPushMatrix();?glTranslatef(100.0f?*?r?-?100.0f,??100.0f?*?g?-?100.0f,??100.0f?*?b?-?100.0f);?DrawSphere((r*9)+(g*3)+b);?glPopMatrix();?}?}?}?glDisable(GL_TEXTURE_2D);?glDisable(GL_TEXTURE_GEN_S);?glDisable(GL_TEXTURE_GEN_T);?}

在我的機器上沒有遮擋查詢下渲染的幀率是20左右。

包圍體

在遮擋查詢中,如果一個物體的邊界都是不可見的,那么就代表這個物體不可見。所以我們只需檢測物體外圍的包圍體可見,就可以判斷物體是否被遮擋。物 體外圍的包圍體包含著整個物體,這也就意味著包圍體的體積是大于等于物體的體積的。對于一個球體來說,包圍體可以有很多種,最常見的就是立方盒子,四面體 等。

為什么要選擇包圍體去判斷遮擋,而不是直接用球體的。因為球體太過于復雜,包含的頂點也多,渲染較耗時。遮擋之所以能夠提升性能,就是我們可以在無 光照,無紋理等其他效果的下,并且不需要改變緩沖區的值,先渲染簡單的包圍體。通過這些包圍體進行深度測試,我們就能判斷出哪些物體被遮擋,那些被遮擋的 物體就可以不需要被渲染(不需要調用任何渲染該物體的命令),如果這個物體擁有非常多的頂點,那么遮擋在這個時候就能大幅度的提高性能。

遮擋查詢

遮擋查詢的步驟:

  • 首先為這些物體生成查詢對象ID 調用glGenQueries

  • 調用glBeginQuery開始遮擋查詢

  • 渲染包圍體

  • 調用glEndQuery 結束遮擋查詢

  • 調用glGetQueryObject[u]iv,根據ID提取遮擋查詢的結果,并根據結果進行相應的操作

  • glDeleteQueries 刪除ID,回收資源

  • 查詢對象的標識符(ID/名稱)是一個無符號整數,我們可以通過glGenQueries函數生成,也可以自己定義。一般用OpenGL提供的glGenQueries會比較方便。

    void glGenQueries(GLsizei n, GLuint *ids);

    第一個參數是生成ID的個數,第二個參數是來存放這些ID的數組。0是保留的ID,不會被產生。我們還可以通過glIsQuery來判斷一個ID是否是一個遮擋查詢對象的ID。

    void glIsQuery(GLuint id);

    如果是返回GL_TRUE,不是則返回GL_FALSE。

    有了遮擋查詢對象的ID后,可以開始遮擋查詢了。例如

    glBeginQuery(GL_SAMPLES_PASSED,?1); glBegin(GL_TRIANGLES);glVertex3f(1.0f,?1.0f,?0.0f);glVertex3f(-1.0f,?5.0f,?0.0f);glVertex3f(6.0f,?20.0f,?0.0f); glEnd(); glEndQuery(GL_SAMPLES_PASSED);

    void glBeginQuery(GLenum target, GLuint id);

    其中target必須是GL_SAMPLES_PASSED. id是用來標識這次遮擋查詢的ID。

    void glEndQuery(GLenum target);結束這次遮擋查詢,其中target必須是GL_SAMPLES_PASSED。

    在完成對需要遮擋查詢的物體渲染之后,我們需要提取遮擋查詢的結果,可以通過glGetQueryObject[u]iv來提取結果,函數將返回片段或采樣的數量。

    void glGetQueryObjectiv(GLenum id, GLenum pname, GLint *param);

    void glGetQueryObjectuiv(GLenum id, GLenum pname, GLuint *param);

    id是這個遮擋查詢對象的id,pname如果是GL_QUERY_RESULT, param將包含了通過深度測試的片段或樣本(如果啟用了多重采樣)的數量,如果數量為0,則表示這個物體完全被遮擋。

    在完成遮擋查詢操作時,可能會有延遲。我們可以通過設置pname為GL_QUERY_RESULT_AVAILABLE來檢查是否完成了。如果遮擋查詢有效地完成了,則param將為GL_TRUE,否則為GL_FALSE.

    例:

    int?count?=?1000;?//等待1000次循環 GLuint?queryReady?=?GL_FALSE; while?(!queryReady?&&?count--) {glGetQueryObjectuiv(1,?GL_QUERY_RESULT_AVAILABLE,?&queryReady); }GLuint?samples;glGetQueryObjectuiv(1,?GL_QUERY_RESULT,?&samples); if(samples?>?0)DrawSomething();

    使用完遮擋查詢對象之后,調用glDeleteQueries回收資源。

    void glDeleteQueries(GLsizei n, const GLuint *ids);

    修改前面的例子,我們可以先渲染27個球體的包圍體,進行遮擋查詢,如果有哪個包圍體被完全遮擋,我們就不需要繪制這個球體了。代碼片段如下:

    void?DrawModels(void)? {?GLint?r,?g,?b;?//繪制主遮擋物DrawOccluder();?//在繪制包圍體時,越簡單越好。關掉紋理,光照等等。//不需要往緩沖區中寫值。glShadeModel(GL_FLAT);?glDisable(GL_LIGHTING);?glDisable(GL_COLOR_MATERIAL);?glDisable(GL_NORMALIZE);?glDepthMask(GL_FALSE);?glColorMask(0,?0,?0,?0);?//?畫27個立方體for?(r?=?0;?r?<?3;?r++)?{?for?(g?=?0;?g?<?3;?g++)?{?for?(b?=?0;?b?<?3;?b++)?{?if?(showBoundingVolume)?glColor3f(r?*?0.5f,?g?*?0.5f,?b?*?0.5f);?glPushMatrix();?glTranslatef(100.0f?*?r?-?100.0f,??100.0f?*?g?-?100.0f,??100.0f?*?b?-?100.0f);?//開始遮擋查詢glBeginQuery(GL_SAMPLES_PASSED,?queryIDs[(r*9)+(g*3)+b]);?//繪制包圍體glutSolidCube(100.0f);?//結束遮擋查詢glEndQuery(GL_SAMPLES_PASSED);?glPopMatrix();?}?}?}//恢復正常的渲染狀態glDisable(GL_POLYGON_STIPPLE);?glShadeModel(GL_SMOOTH);?glEnable(GL_LIGHTING);?glEnable(GL_COLOR_MATERIAL);?glEnable(GL_NORMALIZE);?glColorMask(1,?1,?1,?1);?glDepthMask(GL_TRUE);?//開啟紋理?自動生成紋理坐標glEnable(GL_TEXTURE_2D);?glEnable(GL_TEXTURE_GEN_S);?glEnable(GL_TEXTURE_GEN_T);?//繪制27個不同顏色的球體for?(r?=?0;?r?<?3;?r++)?{?for?(g?=?0;?g?<?3;?g++)?{?for?(b?=?0;?b?<?3;?b++)?{?glColor3f(r?*?0.5f,?g?*?0.5f,?b?*?0.5f);?glPushMatrix();?glTranslatef(100.0f?*?r?-?100.0f,??100.0f?*?g?-?100.0f,??100.0f?*?b?-?100.0f);?//函數中根據,遮擋查詢的結果來判斷是否要繪制這個球體DrawSphere((r*9)+(g*3)+b);?glPopMatrix();?}?}?}?glDisable(GL_TEXTURE_2D);?glDisable(GL_TEXTURE_GEN_S);?glDisable(GL_TEXTURE_GEN_T);? } void?DrawSphere(GLint?sphereNum)? {?GLboolean?occluded?=?GL_FALSE;?if?(occlusionDetection)?{?GLint?passingSamples;?//檢查物體是否被完全遮擋glGetQueryObjectiv(queryIDs[sphereNum],?GL_QUERY_RESULT,??&passingSamples);?if?(passingSamples?==?0)?occluded?=?GL_TRUE;?}?//沒有被遮擋則繪制if?(!occluded)?{?glutSolidSphere(50.0f,?200,?200);?}? }

    有了遮擋查詢后,幀率達到了32左右,當然還要看觀察場景的角度。如果從某個角度看大部分球體都被遮擋了,性能的提升更大。

    ?

    在osg中 example_osgocclusionquery
    一)演示了osg::OcclusionQueryNode的使用。

    轉載于:https://www.cnblogs.com/mazhenyu/p/5083026.html

    超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

    總結

    以上是生活随笔為你收集整理的OpenGL超级宝典笔记——遮挡查询 [转]的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。