如何检测glDrawElements及OpenGL绘制命令是否未生成任何片段?
检测OpenGL绘制命令是否未生成片段的方法
方法一:使用GL_SAMPLES_PASSED查询对象
这是最直接高效的方案,专门用于统计通过所有片段测试的样本数:
- 生成并绑定查询对象:
GLuint queryID; glGenQueries(1, &queryID); - 在绘制命令前后包裹查询逻辑:
glBeginQuery(GL_SAMPLES_PASSED, queryID); glDrawElements(/* 你的绘制参数 */); glEndQuery(GL_SAMPLES_PASSED); - 获取查询结果:
GLuint samplesPassed; // 可先检查结果是否可用避免阻塞:glGetQueryObjectuiv(queryID, GL_QUERY_RESULT_AVAILABLE, &available); glGetQueryObjectuiv(queryID, GL_QUERY_RESULT, &samplesPassed); - 若
samplesPassed为0,说明本次绘制未生成任何有效片段,可直接终止深度剥离的后续迭代。
方法二:利用原子计数器(适合自定义统计场景)
通过片段着色器中的原子计数器统计生成的片段数:
- CPU端创建并初始化原子计数器缓冲区:
GLuint counterBuffer; glGenBuffers(1, &counterBuffer); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterBuffer); glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counterBuffer); - 片段着色器中声明并使用计数器:
layout(binding = 0, offset = 0) uniform atomic_uint fragmentCount; void main() { // 片段通过所有测试后递增计数器 atomicIncrement(fragmentCount); // 你的片段着色逻辑 } - 绘制完成后读取计数器值,若为0则终止迭代;每次迭代前需将计数器重置为0。
深度剥离场景适配要点
每一轮迭代前,以上一轮剥离得到的最大深度作为当前迭代的近裁剪面,设置好对应的深度测试范围后再执行检测逻辑。一旦检测到无片段生成,即可停止后续迭代,避免不必要的绘制开销。
内容的提问来源于stack exchange,提问作者Ivan Folbort
相关产品推荐
相关产品推荐

