GLSL(5)-compute shader小结

感觉和cuda的基本概念是一样的只是叫法不同,cuda中称block,compute shader中同等的概念是work group。一个block中分多个线程,这边就是一个work group中分多个invocation。同时computer shader 中的work group也有一维二维三维的概念,在这方面和cuda几乎都是一样的。cuda中计算线程索引的方法和compute shader中计算invocation中的也一样。

然后还有很重要的特别要注意的一点就是,compute shader不属于渲染管线中的任何一个阶段,所以它的需要一个单独的program handle来处理它,要和平时专门用来渲染render program handle区分开,两者的compile(),link(),还有program的use()也需要分别进行,否则会报错。

下面是粒子运动的compute shader实现代码:

#version 430
//指定当前block中横向有1000个线程(每个线程处理一个粒子,opengl那边除以1000,这边定义1000,和cuda都一样的道理
//纵向0个,因为当前使用的是一维的block
//这句在glsl-compute shader中的概念:定义一个work group 中有多少个invocation
layout( local_size_x = 1000 ) in;

uniform float Gravity1 = 1000.0;
uniform vec3 BlackHolePos1 = vec3(5,0,0);

uniform float Gravity2 = 1000.0;
uniform vec3 BlackHolePos2 = vec3(-5,0,0);

uniform float ParticleMass = 0.1;
//粒子质量的倒数,预计算出来,后面直接用
uniform float ParticleInvMass = 1.0 / 0.1;
uniform float DeltaT = 0.0005;
uniform float MaxDist = 45.0;

layout(std430, binding=0) buffer Pos {
  vec4 Position[];
};
layout(std430, binding=1) buffer Vel {
  vec4 Velocity[];
};
//attractor是唯一会影响粒子移动的物体,本例子中使用了两个attractor
//这个atractor会给粒子带来一股作用力,像是万有引力的吸引力,所以这个引力是和距离(粒子与attractor的距离)的平方成反比的,
//计算力--得到粒子运动的加速度--根据初速度和当前速度的计算公式得到当前速度--计算当前的粒子位置--更新粒子位置--渲染到屏幕上done.
void main() 
{
  //这个gl_GlobalInvocationID.x,相当于就是block中线程的id.x。
  //因为这里只用到了一维,所以自然这里直接用= gl_GlobalInvocationID.x;就好了
  //如果是二维的,那么就是:gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID.x(.y)
  uint idx = gl_GlobalInvocationID.x;//获得当前Invocation的索引

  vec3 p = Position[idx].xyz;//根据索引,从Position数组中取得坐标xyz

  // Force from black hole #1
  vec3 d = BlackHolePos1 - p;
  float dist = length(d);//计算attractor1与当前粒子之间的距离
  vec3 force = (Gravity1 / dist) * normalize(d);//计算出attractor1给当前粒子施加的作用力大小

  //下面同理是attractor2
  // Force from black hole #2
  d = BlackHolePos2 - p;
  dist = length(d);
  force += (Gravity2 / dist) * normalize(d);//作用力的总和

  // Reset particles that get too far from the attractors
  if( dist > MaxDist ) 
  {
    Position[idx] = vec4(0,0,0,1);
  } 
  else 
  {
    // Apply simple Euler integrator
    vec3 a = force * ParticleInvMass;//计算出加速度=合力*质量的倒数
	//下面更新速度和位置
    Position[idx] = vec4(
        p + Velocity[idx].xyz * DeltaT + 0.5 * a * DeltaT * DeltaT, 1.0);//起点+初速度*时间+二分之一加速度的平方=路程
    Velocity[idx] = vec4( Velocity[idx].xyz + a * DeltaT, 0.0);
  }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenGL Compute Shader是OpenGL 4.3引入的一种新型Shader,它主要用于通用计算(GPGPU)任务而不是图形渲染。它可以在GPU上执行高度并行的计算任务,例如物理模拟、图像处理和机器学习等。Compute Shader与其他Shader不同之处在于它没有渲染管道的输入和输出,并且可以从CPU上下文中直接调用。它还可以读写各种类型的缓冲区和纹理,使其非常灵活和强大。 Compute Shader的使用步骤如下: 1.创建Compute Shader对象:使用glCreateShader函数创建Compute Shader对象。 2.编译Compute Shader代码:使用glShaderSource和glCompileShader函数将Compute Shader代码编译为OpenGL可识别的二进制格式。 3.创建Compute Program对象:使用glCreateProgram函数创建Compute Program对象。 4.将Compute Shader附加到Compute Program对象上:使用glAttachShader函数将Compute Shader附加到Compute Program对象上。 5.链接Compute Program对象:使用glLinkProgram函数将Compute Program对象链接到OpenGL渲染管道。 6.使用Compute Shader:使用glUseProgram函数激活Compute Program对象,并通过glDispatchCompute函数调用Compute Shader。 7.清理资源:使用glDeleteShader和glDeleteProgram函数删除Compute ShaderCompute Program对象。 下面是一个简单的Compute Shader示例代码: ```glsl #version 430 layout(local_size_x = 16, local_size_y = 16) in; layout(std430, binding = 0) buffer InputBuffer { float data[]; }; layout(std430, binding = 1) buffer OutputBuffer { float result[]; }; void main() { uint idx = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x; result[idx] = data[idx] * data[idx]; } ``` 这个Compute Shader使用输入缓冲区和输出缓冲区,对输入缓冲区的每个元素进行平方运算,并将结果存储在输出缓冲区中。在主函数中,使用gl_GlobalInvocationID获取全局线程ID,计算出要处理的输入元素的索引,并在输出缓冲区中存储计算结果。 最后,通过调用glDispatchCompute函数启动Compute Shader。该函数需要指定调度的工作组数量,以及每个工作组中线程的数量。在这个示例中,我们使用16x16的工作组,并将其应用于输入缓冲区的所有元素。 ```c++ glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ); ``` 以上就是OpenGL Compute Shader的原理与使用方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值