zoukankan      html  css  js  c++  java
  • 粒子系统—雪景模拟

    1. 粒子系统

    粒子系统是用来模拟微小粒子的物理学模型,一般用于火焰、爆炸等由微小粒子组成的物理现象的模拟。一般而言,粒子系统由大量具有颜色、位置、速度等特征的粒子组成。通常用于游戏中的特效或者雨雪、火焰等模拟。

    2.粒子的属性:

    • 位置
    • 速度
    • 颜色
    • 声明周期
    • 重力

    一般而言粒子具有以上的属性,但是可以根据具体的情况来增加或者减少一些属性,还可以给粒子加上其他物理特性,如可以让落在地面的粒子反弹等。

    3.下雪效果的粒子系统

    这里给出一个opengl实现的模拟下雪效果的粒子系统,具体代码如下:

    // particles.h
    #ifndef OPENGLUS_EXAMPLES_PARTICLES_H
    #define OPENGLUS_EXAMPLES_PARTICLES_H
    #include <vector>
    #include <random>
    
    #include "instance.h"
    #include "program.h"
    
    #include "glm/glm.hpp"
    
    namespace openglus {
    
    struct Particle {
    public:
      Particle( )
        : offset(area_randomer(e), 200.0f, area_randomer(e)),
        speed(0.0f, speed_randomer(e), 0.0f), size(size_randomer(e))
      { }
    
    public:
      static std::default_random_engine e;
      static std::uniform_real_distribution<double> speed_randomer;
      static std::uniform_int_distribution<unsigned> size_randomer;
      static std::uniform_real_distribution<double> area_randomer;
    
    public:
      glm::vec3 offset, speed;
      GLfloat size;
    };
    
    
    class ParticleSystem {
    public:
      ParticleSystem(GLuint max_particles);
      void Update(GLfloat time_passed, const glm::vec3& camera_pos);
      void Draw(Program& program);
    
    private:
      void Init( );
      void BufferData();
    
    private:
      GLuint nums_;
      std::vector<Particle> particles_;
      Instance<GLfloat> snow_instance_;
      std::vector<glm::vec3> offset_;
      std::vector<GLfloat> size_;
    };
    
    } // namespace openglus
    
    #endif // OPENGLUS_EXAMPLES_PARTICLES_H
    

    在该粒子系统中,雪粒子只有位置、大小与速度不同,其他属性都被忽略,对于雪粒子,在opengl中使用GL_POINTS模式绘制,并且给粒子贴上雪的纹理,采用instance形式绘制,会提高效率。
    // particles.cc
    #include "particles.h"
    
    #include <algorithm>
    #include <random>
    #include <cstddef>
    
    #include "gl/glew.h"
    
    namespace openglus {
    
    std::default_random_engine Particle::e;
    std::uniform_real_distribution<double> Particle::speed_randomer(2.0, 5.0);
    std::uniform_int_distribution<unsigned> Particle::size_randomer(3, 10);
    std::uniform_real_distribution<double> Particle::area_randomer(-100, 100);
    
    ParticleSystem::ParticleSystem(GLuint max_particles)
      : nums_(max_particles), particles_(max_particles), snow_instance_({0.0f, 0.0f, 0.0f})
    {
      Init( );
    }
    
    
    void ParticleSystem::Init( )
    {
      snow_instance_.SetBaseMeshAttribute(0, 3, GL_FLOAT, 3 * sizeof(GLfloat));
      snow_instance_.AddInstanceAttribute(nums_ * 3 * sizeof(GLfloat), 1, 3, GL_FLOAT, 3 * sizeof(GLfloat));
      snow_instance_.AddInstanceAttribute(nums_ * sizeof(GLfloat), 2, 1, GL_FLOAT, sizeof(GLfloat));
    }
    
    
    void ParticleSystem::Update(GLfloat time_passed, const glm::vec3& camera_pos)
    {
      std::vector<glm::vec3> offset;
      std::vector<GLfloat> size;
      
      for (int i = 0; i < nums_; ++i) {
        Particle& p = particles_[i];
        if (p.offset.y > 0.0f) {
          p.offset -= p.speed * time_passed * 5.0f;
          offset.push_back(glm::vec3(p.offset));
          size.push_back(p.size);
        } else {
          p = Particle( );
        }
      }
      std::swap(offset_, offset);
      std::swap(size_, size);
      BufferData();
    }
    
    
    void ParticleSystem::BufferData()
    {
      snow_instance_.BufferStreamData(1, offset_.size( ) * 3 * sizeof(GLfloat), offset_.data( ));
      snow_instance_.BufferStreamData(2, size_.size( ) * sizeof(GLfloat), size_.data( ));
    }
    
    void ParticleSystem::Draw(Program& program)
    {
      snow_instance_.DrawArray(program, 1, offset_.size( ), GL_POINTS);
    }
    
    } // namespace openglus
    

    绘制效果:

  • 相关阅读:
    SQL2012 创建备份计划
    rem 移动端适配
    sql server 表结构 导出 到excel
    针对OAuth2的CSRF攻击
    xss、SQL测试用例小结
    svn报错:[Previous operation has not finished; run 'cleanup' if it was interrupted] 的排错过程
    并发数与在线用户之间的关系
    loadrunner--常用函数列表【转】
    LR参数化类型为file显示大于100数据方法
    loadrunner11--集合点(Rendezvous )菜单是灰色不能点击
  • 原文地址:https://www.cnblogs.com/tallisHe/p/5539417.html
Copyright © 2011-2022 走看看