【OpenGL蓝宝书】Chapter 12. Controlling and Monitoring the Pipeline

一、Queries

你可以向OpenGL的渲染管线“提问题”,问它现在的某个状况如何。就像上课提问要举手,你向OpenGL提问也要先举手。举手的时候,老师不知道你想问啥,但已经知道你有问题了。举手的操作就是glGenQueries(1, &query),query可以理解为“你”这个提问的人。和glGenTextures()很像有木有!

举手之后就提问,使用glBeginQuery(target, query);glEndQuery(target)。其中target就是你想问的问题。OpenGL已经预置了如GL_SAMPLES_PASSED之类的问题类型。

GL_SAMPLES_PASSED问的是:在BeginQuery和EndQuery之间的渲染有多少次采样通过了深度测试。之后会把结果告诉query(不是直接赋值哦,是把结果告诉这个人)。

想要取得这个值,就要使用glGetQueryObjectuiv(query, GL_QUERY_RESULT, &result);让query把结果存进result。

利用以上特性,可以有一个优化渲染的想法:将复杂的图形先简化(通常情况下bounding box即可),然后渲染简化的模型。然后向pipeline提问:有多少采样通过了深度测试呀?如果返回不为0,那说明这个图形在界面中是可见的,然后就可以渲染他了。示例代码如下:

// code 1: basic query
glGenQueries(1, &query);    // 举手
glBeginQuery(GL_SAMPLES_PASSED, query);    // 提问
RenderSimplifiedObject(object);    // 渲染bounding box
glEndQuery(GL_SAMPLES_PASSED);    // 结束提问
glGetQueryObjectuiv(query, GL_QUERY_RESULT, &result);    // 统计
if (the_result != 0)
    RenderRealObject(object);    // 渲染真图形

另外一种情况是,BeginQuery和EndQuery之间的渲染太多啦,在你取值时还没统计完,这会导致OpenGL程序卡在这,等它统计。这就导致OpenGL程序优化不行。有个方法可以检查这个值统计好没,就是glGetQueryObjectuiv(query, GL_QUERY_RESULT_AVAILABLE, &result)。统计好了,result==GL_TRUE;没统计好,result==GL_FALSE。

再回到之前这个优化渲染的想法:如果统计简化图形(bounding box)渲染的深度测试通过数量时发生了上述问题,则完全不必担心:result没有准备好就算了呗,我们只想知道跳过这个图形安不安全,result没好咱就不等了,只要把确定可以跳过的跳过就行了。优化过的代码如下:

// code 2: 老子不等啦
glGenQueries(1, &query);
glBeginQuery(GL_SAMPLES_PASSED, query);
RenderSimplifiedObject(object);
glEndQuery(GL_SAMPLES_PASSED);
glGetQueryObjectuiv(query, GL_QUERY_RESULT_AVAILABLE, &result);    // 问它result能用了嘛
if (result == GL_TRUE)    // 能用啦
    glGetQueryObjectuiv(the_query, GL_QUERY_RESULT, &result);    // 告诉我通过多少吧
else
    result = 1;    // result还不能用?那老子不等了

if (result != 0)
    RenderRealObject(object);

像这样取得具体数值固然可行,但我们的工作并不建立在具体数值上。因此,可以进一步使用条件渲染(Conditional Render)。所有夹在glBeginConditionalRender(query, mode)和glEndConditionalRender(query, mode)之间的“渲染指令”将会在query得到0时全部跳过。

其中mode可以选GL_QUERY_WAIT和GL_QUERY_NO_WAIT,表示要不要等query统计完返回值。如过不等,则若result尚未available时,后续渲染指令就会无条件执行。因此,上述代码还能再优化:

// code 3: 老子都不用取回来
glGenQueries(1, &query);
glBeginQuery(GL_SAMPLES_PASSED, query);
RenderSimplifiedObject(object);
glEndQuery(GL_SAMPLES_PASSED);

// 条件渲染
glBeginConditionalRender(query, GL_QUERY_NO_WAIT);    // 根据query取得的值决定接下来的渲染:若还没取到值则无条件渲染
RenderRealObject(object);
glEndConditionalRender();

像这种统计采样点的query,叫做Occlusion Queries。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值