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);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值