Occlusion Query (ARB_occlusion_query 扩展的使用)

1649 篇文章 12 订阅
1623 篇文章 23 订阅
Occlusion Query 的用处
  • 增量的物体级别的剔除
  • 顺序独立的透明
  • 光晕效果实现
  • 模板阴影
这个例子中, 我们绘制一个板和一个球,
板用黄色绘制, 球用红色绘制.
我们利用 Occlusion Query 来查询到他们分别显示在屏幕上的Fragment Count.

首先定义一些需要的函数指针
把他们定义为全局变量.
PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL;
PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB = NULL;
PFNGLISQUERYARBPROC glIsQueryARB = NULL;
PFNGLBEGINQUERYARBPROC glBeginQueryARB = NULL;
PFNGLENDQUERYARBPROC glEndQueryARB = NULL;
PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL;
PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL;
PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL;
然后我们来初始化这个扩展
首先获得Token, 然后查询是否支持,
如果支持了, 就初始化这些函数指针.
char *ext = (char*)glGetString( GL_EXTENSIONS );

if( strstr( ext, "GL_ARB_occlusion_query" ) == NULL )
{
MessageBox(NULL,"GL_ARB_occlusion_query extension was not found",
"ERROR",MB_OK|MB_ICONEXCLAMATION);
return;
}
else
{
glGenQueriesARB = (PFNGLGENQUERIESARBPROC)wglGetProcAddress("glGenQueriesARB");
glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)wglGetProcAddress("glDeleteQueriesARB");
glIsQueryARB = (PFNGLISQUERYARBPROC)wglGetProcAddress("glIsQueryARB");
glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)wglGetProcAddress("glBeginQueryARB");
glEndQueryARB = (PFNGLENDQUERYARBPROC)wglGetProcAddress("glEndQueryARB");
glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)wglGetProcAddress("glGetQueryivARB");
glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)wglGetProcAddress("glGetQueryObjectivARB");
glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)wglGetProcAddress("glGetQueryObjectuivARB");

if(
!glGenQueriesARB || !glDeleteQueriesARB || !glIsQueryARB ||
!glBeginQueryARB || !glEndQueryARB || !glGetQueryivARB ||
!glGetQueryObjectivARB || !glGetQueryObjectuivARB
)
{
MessageBox(NULL,"One or more GL_ARB_occlusion_query functions were not found",
"ERROR",MB_OK|MB_ICONEXCLAMATION);
return;
}
}
然后我们来创建查询.
g_sphereQuery, g_planeQuery 为GLuint,
记录创建后此'查询'的ID.

在这里我们创建了两个查询,
一个查询球的,一个查询板的.
glGenQueriesARB( 1, &g_sphereQuery );
glGenQueriesARB( 1, &g_planeQuery );
当然在我们关闭程序
或者不再需要查询的时候,
要释放查询
glDeleteQueriesARB( 1, &g_sphereQuery );
glDeleteQueriesARB( 1, &g_planeQuery );
然后就是渲染循环部分处理的事情了,
1.首先初始化深度缓存.
其实没有什么很特别的东西,
就是把球和板画一遍, 填充下深度.
glPushMatrix();
{
glTranslatef( 0.0f, -0.025f, 0.0f);
glScalef( 1.0f, 0.05f, 1.0f );
glColor3f( 1.0f, 1.0f, 0.0f );
renderSolidCube( 0.435f );
}
glPopMatrix();

glPushMatrix();
{
glTranslatef( 0.0f, 0.25f, 0.0f );
glColor3f( 1.0f, 0.0f, 0.0f );
renderSolidSphere( 0.25f, 20, 20 );
}
glPopMatrix();
2.开始Occlusion Query查询.
又要重绘一遍,
这一遍可以把材质什么的都去掉, 这些对查询无用.
//
// Render the plane first and wrap it with an occlusion query
//

glPushMatrix();
{
glTranslatef( 0.0f, -0.025f, 0.0f);
glScalef( 1.0f, 0.05f, 1.0f );

glBeginQueryARB( GL_SAMPLES_PASSED_ARB, g_planeQuery );
{
glColor3f( 1.0f, 1.0f, 0.0f );
renderSolidCube( 0.435f );
}
glEndQueryARB( GL_SAMPLES_PASSED_ARB );
}
glPopMatrix();

//
// Render the sphere second and wrap it with an occlusion query
//

glPushMatrix();
{
glTranslatef( 0.0f, 0.25f, 0.0f );

glBeginQueryARB( GL_SAMPLES_PASSED_ARB, g_sphereQuery );
{
glColor3f( 1.0f, 0.0f, 0.0f );
renderSolidSphere( 0.25f, 20, 20 );
}
glEndQueryARB( GL_SAMPLES_PASSED_ARB );
}
glPopMatrix();
当以上两步都做完后, 我们就可以来读取查询结果了.
读取结果过程如下:
planeFragmentCount, sphereFragmentCount 就是分别读取的Fragement Count.
然后用文本显示出来了.
GLuint planeFragmentCount;
GLuint sphereFragmentCount;
char planeString[50];
char sphereString[50];

glGetQueryObjectuivARB( g_planeQuery, GL_QUERY_RESULT_ARB, &planeFragmentCount);
glGetQueryObjectuivARB( g_sphereQuery, GL_QUERY_RESULT_ARB, &sphereFragmentCount);

sprintf( planeString, "Plane Fragments = %d", planeFragmentCount );
sprintf( sphereString, "Sphere Fragments = %d", sphereFragmentCount );

beginRenderText( g_nWindowWidth, g_nWindowHeight );
{
glColor3f( 1.0f, 1.0f, 1.0f );
renderText( 5, 15, BITMAP_FONT_TYPE_HELVETICA_12, planeString );
renderText( 5, 30, BITMAP_FONT_TYPE_HELVETICA_12, sphereString );
}
endRenderText();
以下就是完成一个Occlusion Query的大致步骤,
参考代码在这里可以找到:
http://www.codesampler.com/oglsrc/oglsrc_7.htm#ogl_occlusion_query
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值