• 风场可视化:随机重置


    引子

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

    原因

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

    解决方案

    需要考虑的问题有:

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

    什么时候重置?

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

    重置的判断条件是什么?

    相关的主要逻辑如下:

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

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

    参考资料

  • 相关阅读:
    CareerCup Questions List 职业杯题目列表
    [CareerCup] Guards in a museum 博物馆的警卫
    [LeetCode] 7. Reverse Integer 翻转整数
    Python笔记11------一个K-means聚类的小例子
    python笔记10-----便捷网络数据NLTK语料库
    Python笔记9-----不等长列表转化成DataFrame
    Python笔记8----DataFrame(二维)
    Python笔记7----Pandas中变长字典Series
    Python笔记6----数组
    Python笔记5----集合set
  • 原文地址:https://www.cnblogs.com/thyshare/p/16025485.html
Copyright © 2020-2023  润新知