Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

随机重置 #106

Open
XXHolic opened this issue Feb 3, 2022 · 0 comments
Open

随机重置 #106

XXHolic opened this issue Feb 3, 2022 · 0 comments

Comments

@XXHolic
Copy link
Owner

XXHolic commented Feb 3, 2022

引子

绘制轨迹的效果中,过一段时间就会发现,最后只剩下固定的几条轨迹,原文中也提到了这种现象,也提供了解决思路,个人还是想结合源码再看看。

原因

随着时间推移,有些粒子产生的偏移超过了范围就会消失,所以需要随机重置消失的风粒子。

解决方案

需要考虑的问题有:

  • 什么时候重置?
  • 重置的判断条件是什么?
  • 重置的方式是什么?

什么时候重置?

绘制轨迹中,我们知道了产生的偏移是在最后更新粒子纹理信息阶段,这个时机判断保留新的粒子状态还是重置比较合适。

重置的判断条件是什么?

相关的主要逻辑如下:

const updateFrag = `
uniform float u_rand_seed;
uniform float u_drop_rate;
uniform float u_drop_rate_bump;

// pseudo-random generator
const vec3 rand_constants = vec3(12.9898, 78.233, 4375.85453);
float rand(const vec2 co) {
    float t = dot(rand_constants.xy, co);
    return fract(sin(t) * (rand_constants.z + t));
}

void main() {
  vec4 color = texture2D(u_particles, v_tex_pos);
  vec2 pos = vec2(
      color.r / 255.0 + color.b,
      color.g / 255.0 + color.a); // decode particle position from pixel RGBA

  vec2 velocity = mix(u_wind_min, u_wind_max, lookup_wind(pos));
  float speed_t = length(velocity) / length(u_wind_max);

  pos = fract(1.0 + pos + offset);
  // a random seed to use for the particle drop
  vec2 seed = (pos + v_tex_pos) * u_rand_seed;

  // drop rate is a chance a particle will restart at random position, to avoid degeneration
  float drop_rate = u_drop_rate + speed_t * u_drop_rate_bump;
  float drop = step(1.0 - drop_rate, rand(seed));

  vec2 random_pos = vec2(
      rand(seed + 1.3),
      rand(seed + 2.1));
  pos = mix(pos, random_pos, drop);
}
`
this.dropRate = 0.003; // how often the particles move to a random place
this.dropRateBump = 0.01; // drop rate increase relative to individual particle speed
// 代码省略
gl.uniform1f(program.u_rand_seed, Math.random());
gl.uniform1f(program.u_drop_rate, this.dropRate);
gl.uniform1f(program.u_drop_rate_bump, this.dropRateBump);

先介绍一下内置函数:

  • step(edge, x):如果 x < edge ,则返回 0.0 ,否则返回 1.0 。
vec2 seed = (pos + v_tex_pos) * u_rand_seed;

得到的偏移后的位置 pos 加上顶点位置 v_tex_pos ,乘以随机 [0, 1) 之间的随机数 u_rand_seed ,得到一个随机粒子位置 seed

float drop_rate = u_drop_rate + speed_t * u_drop_rate_bump;

粒子插值百分比 speed_t 乘以自定义单个粒子流失率 u_drop_rate_bump ,再加上自定义整体流失率,得到综合流失率 drop_rate

float drop = step(1.0 - drop_rate, rand(seed));

如果 rand(seed) 小于综合非流失率 1.0 - drop_rate ,那么 drop = 0 ,表示不会重置粒子,否则就会重置粒子。

重置的方式是什么?

重置的方式就是上面的这部分:

const vec3 rand_constants = vec3(12.9898, 78.233, 4375.85453);
float rand(const vec2 co) {
    float t = dot(rand_constants.xy, co);
    return fract(sin(t) * (rand_constants.z + t));
}

vec2 seed = (pos + v_tex_pos) * u_rand_seed;
vec2 random_pos = vec2(
    rand(seed + 1.3),
    rand(seed + 2.1));

这个主要就是原文中所说生成伪随机数。至于为什么用这样的计算方式,需要在数学方面下功夫。

参考资料

🗑️

最近看了下韩国的丧尸剧《僵尸校园》,然后去看了原版本的漫画结局,发现改编了不少,不过改的也可以。

这个体裁在韩剧也不算是新鲜了,很长时间没有看这类剧的话,看看还行。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant