有关师德建设的网站linux服务器安装网站
|   本篇在讲什么 本篇为蓝宝书学习笔记 原子计数器 本篇适合什么 适合初学Open的小白 本篇需要什么 对C++语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上手 提供全流程的源码内容  | 
   ★提高阅读体验★ 👉 ♠ 一级标题 👈👉 ♥ 二级标题 👈👉 ♣ 三级标题 👈👉 ♦ 四级标题 👈 | 
目录
- ♠ 原子计数器
 - ♠ 用法
 - ♥ 声明
 - ♥ 绑定
 - ♥ 重置
 - ♥ 计数
 
- ♠ 案例
 - ♠ 推送
 - ♠ 结语
 
♠ 原子计数器
- 什么是原子计数器
 
原子计数器是一种特殊的变量,表示的是多个着色器之间共享的存储,这个存储和一个缓冲对象关联,而且我们可以调用特定的函数进行原子内存操作
- 原子计数器的作用
 
变量本身的功能是用于计数
♠ 用法
♥ 声明
layout (binding=3,offset=8) uniform atomic_uint my_variable;
 
声明了原子计数器my_variable,并绑定在3上,其中起始位置是8
♥ 绑定
GLuint buf;
glGenBuffers(1, &buf); 
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buf); 
glBufferData(GL_ATOMIC_COUNTER_BUFFER, 16 * sizeof(GLuint), NULL, GL_DYNAMIC_COPY);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 3, buf);
 
同uniform和buffer相同,可以使用相同的方式将缓存对象绑定至绑定点上,特定参数GL_ATOMIC_COUNTER_BUFFER
♥ 重置
在使用前我们要重置计数器变量,书中提供了三种方式重设变量
- glBufferSubData
 
const GLuint zero = 0; 
glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 2 * sizeof(GLuint), sizeof(GLuint), &zero);
 
通过glBufferSubData更新指定位置的数据
- glMapBufferRange
 
GLuint * data = (GLuint *)glMapBufferRange(GL ATOMIC COUNTER BUFFER, 0, 16 * sizeof(GLuint), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
data[2] = 0;
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
 
通过glMapBufferRange获取变量地址后直接赋值
- glClearBufferSubData
 
glClearBufferSubData(GL_ATOMIC_COUNTER_BUFFER, GL_R32UI, 2 * sizeof(GLuint), sizeof(GLuint), GL_RED_INTEGER, GL_UNSIGNED_INT, &zero);
 
通过glClearBufferSubData赋值
♥ 计数
OpenGL提供了三种用于计数的着色器函数
- 加一
 
uint atomicCounterIncrement(atomic_uint a);
 
- 减一
 
uint atomicCounterDecrement(atomic_uint a);
 
- 获取值
 
uint atomicCounter(atomic_uint a);
 
♠ 案例
我们来看一个完整的演示示例吧,改例子将一个计数器绑定到缓存后并清零,通过计数器的数量来判断颜色的显示
注:该例子直接修改OpenGl超级宝典官方示例singletri.cpp,只需修改startup方法即可
virtual void startup()
{static const char * vs_source[] ={"#version 450 core                                                 \n""                                                                  \n"" 																   \n""void main(void)                                                   \n""{                                                                 \n""    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),  \n""                                   vec4(-0.25, -0.25, 0.5, 1.0),  \n""                                   vec4( 0.25,  0.25, 0.5, 1.0)); \n""                                                                  \n""    gl_Position = vertices[gl_VertexID];                          \n""}                                                                 \n"};static const char * fs_source[] ={"#version 450 core												   \n""																   \n""																   \n""layout (binding=0) uniform atomic_uint my_variable;	           \n""																   \n""out vec4 color;												   \n""																   \n""void main(void)                                                   \n""{																   \n""    uint counter = atomicCounterIncrement(my_variable);		   \n""	 if(counter>20000){										       \n""		 color = vec4(1.0, 0.8, 1.0, 1.0);						   \n""	 }else{														   \n""		 color = vec4(0.0, 0.8, 1.0, 1.0);						   \n""    }															   \n"																		"}											                       \n"};program = glCreateProgram();GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fs, 1, fs_source, NULL);glCompileShader(fs);GLuint vs = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vs, 1, vs_source, NULL);glCompileShader(vs);glAttachShader(program, vs);glAttachShader(program, fs);glLinkProgram(program);glGenVertexArrays(1, &vao);glBindVertexArray(vao);// 绑定缓存GLuint buf;glGenBuffers(1, &buf);glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buf);glBufferData(GL_ATOMIC_COUNTER_BUFFER, 16 * sizeof(GLuint), NULL, GL_DYNAMIC_COPY);glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, buf);// 清零计数器const GLuint zero = 0;glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 2 * sizeof(GLuint), sizeof(GLuint), &zero);
}
 
在counter>20000下显示效果如下

在counter<20000下显示效果如下

♠ 推送
- Github
 
https://github.com/KingSun5
 
♠ 结语
若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。
