本篇在讲什么 OpenGL蓝宝书第十章学习笔记计算着色器 本篇适合什么 适合初学OpenGL的小白 本篇需要什么 对C++语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上手 提供全流程的源码内容 |
★提高阅读体验★ 👉 ♠ 一级标题 👈👉 ♥ 二级标题 👈👉 ♣ 三级标题 👈👉 ♦ 四级标题 👈 |
♠ 本章的学习要点
- 如何创建、编译和调度计算着色器
- 如何在计算着色器调用之间传递数据
- 如何同步计算着色器并有序运行
♠ 计算着色器概述
- 计算着色器是一种利用图形处理器的强大计算能力实现OpenGL的途径
- 除其他着色器可用的贴图、存储缓存和原子内存操作等机制外,计算着色器还能实现相互同步和共享数据,从而简化常规计算
- 计算着色器与其他OpenGL管线均不同,旨在尽可能为应用程字开发人员提供尽可能多的灵活性
简单理解,计算着色器通过共享内存和线程同步功能,采用更有效的方式去处理数据
♠ 使用计算着色器
计算着色器与其他任何着色器是相同的。在GLSL语言中声明着色器对象,并链接到程序对象上,如下述代码所示
static const GLchar * compute_source[]
{
"#version 450 core \n"
"layout (local_size_x = 32,local_size_y = 32) in; \n"
"void main(void) \n"
"{ \n"
" //Do nothing \n"
"} \n"
}
compute_shader = glCreateshader(GL_COMPUTE_SHADER);
glshaderSource(compute_shader,1,compute_source,NULL);
glCompileShader(compute_shader);
compute_program = glCreateprogram();
glAttachShader(compute_program, compute_shader);
glLinkProgram(compute program);
注意:
这里创建shader使用的参数是GL_COMPUTE_SHADER
注意:
在同一个program
程序上,计算着色器只能单独使用,不能和其他着色器混用
♥ 执行计算着色器
两个关键执行函数,设置全局工作组和局部工作组
void glDispatchCompute(GLuint num_groups_x,GLuint num_groups_y,GLuint num_groups_z);
void glDispatchComputeIndirect(GLintptr indirect);
♣ 全局和局部工作组
调用一次二者任意一个会有一个全局工作组
发送到OpenGL用于处理
x、y、z坐标的局部工作组数量由参数num_groups_x、num_groups_y、num_groups_z决定
可通过调用函数glGetIntegeri_v()
获取工作组的最大尺寸或单一工作组所能够完成的最大调用总数
可通过调用函数g1Getprogramiv()
即可确定程序计算着色器的局部工作组尺寸
♣ 计算着色器输入与输出
计算着色器并无内置输出
前后无任何工序的单工序管线
有一些内置输入变量可用于确定目前在局部工作组和更大全局工作组中的所处位置线
-
gl_LocalInvocationID:着色器调用在局部工作组内的索引
-
gl_workGroupsize:储存局部工作组尺寸
-
gl_NumWorkGroups:工作组数量
-
gl_WorkGroupID:当前工作组在全局数据集中的索引
-
gl_LocalInvocationIndex:代码将 3D 变量转换成 1D 索引
♥ 计算着色器通信
计算着色器可以用共享存储限定符声明变量,从而在同一局部工作组内运行的计算着色器之间实现共享,访问速度很快
共享内存很小,只有几kb,可以通过调用函数glGetIntegerv()
来确定
♣ 同步计算着色器
执行barrier()
函数,可执行流控制屏障,调用是应阻止调用直到同一局部工作组内的其他所有着色器调用均已达到着色器内的那一点
使用共享内存是,流控制屏障很重要,可以确定局部工作组内其他着色器当前调用到同一点上的具体时间
♠ 推送
- Github
https://github.com/KingSun5
♠ 结语
若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。