OpenGL超级宝典(第7版)笔记22 原子计数器 清单5.31-5.34
文章目录
前言
上一篇我们介绍了着色器存储区块的相关内容(包括了和uniform块的对比),还介绍了原子内存操作和屏障的实用问题。这一篇我们将介绍原子计数器,我们将通过它来进行计数,并通过它计算图形的面积。
1 原子计数器初介绍
原子计数器是一种特殊的变量,表示的是多个着色器之间共享的存储(即大家都可以对该变量进行修改),而且我们可以调用特定的函数进行原子内存操作。变量本身的功能是用于计数。
1.1 原子计数器的声明
layout (binding=2,offset=8) uniform atomic_uint mycounter;
这里声明了原子计数器mycounter,并绑定在2上,其中起始位置是8。
1.2 原子计数器准备缓冲
首先为原子计数器变量准备一些内存,以便其使用:
GLuint Atomic_counter_buffer;
glCreateBuffers(1, &Atomic_counter_buffer);
glNamedBufferStorage(Atomic_counter_buffer, 16*sizeof(GLuint), NULL, GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT );
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER,2,Atomic_counter_buffer);
我们要将缓冲中清零:
GLuint atomic_counter_data=0;
glClearNamedBufferSubData(Atomic_counter_buffer,GL_R32UI,2*sizeof(GLuint),sizeof(GLuint),GL_RED_INTEGER,GL_UNSIGNED_INT,&atomic_counter_data);
当然你可以才用书上的其他方法也可以把它清零(使用glNamedBufferSubData或是使用glMapBufferRange的指针来进行清零也可以)
1.3 使用原子计数器计数
我们现在在着色器中已经声明了原子计数器,并且在我们的程序中为该原子计数器安排了内存并做了初始化,现在我们要在着色器内部用原子计数器进行计数。OpenGL提供了三种用于计数的着色器函数:
uint atomicCounterIncrement(atomic_uint a);//让计数器加一
uint atomicCounterDecrement(atomic_uint a);//让计数器减一
uint atomicCounter(atomic_uint a);//返回计数器的值
我们现在改写一下片段着色器:
#version 450 core
layout (binding=2,offset=8) uniform atomic_uint mycounter;
in vec4 fscolor;
out vec4 color;
void main(void){
atomicCounterIncrement(mycounter);
color = fscolor;
}
我们的想法是在每次运行片段着色器的时候都对计数器进行加一,这样我们在运算完一帧画面后计数器的数字就是所绘制的像素数,如果我们绘制的图像充满了整个窗口,那么计数