2011-08-01 116 views
-1

我想用OpenGL做一个雪花片的动画。任何人都可以建议我一些教程或示例代码?OpenGL中的雪花模拟?

+1

是否意味着像雪花一样的粒子系统或动画雪花图片? –

+0

yup using particle system – bharru

回答

2

一个可能的解决方案是使用particle system。我曾经从中得到过一些爆炸效果,我认为这与你想要的非常接近。

这里的one of the tutorials I used,我认为这可能会有所帮助(顺便说一句,有很多很好的教程在该网站上,你可以检查出来)。另外,对于雪花片的生成,你可以使用相同的片,但如果你想要更漂亮的东西(不是太花哨,但相对容易),你可以使用三角形条纹(本教程使用它)来实现因为雪花片是对称的,所以效果更好。

+1

NeHe教程已弃用。与缓冲区对象相比,使用固定功能管道和即时模式非常慢。 – Tamschi

2

如果您要使用3D雪花,则可以使用transform feedback来计算顶点着色器中的粒子物理,并使用instancingPoint sprites应该使广告牌更快,并使用更少的内存来存储顶点。 (每个雪花只需要一个。)

在顶点着色器中运行粒子系统会使其速度提高几倍,而数学本质上保持不变。

您也可以使用3D纹理抵消阻尼计算,以便可以看到湍流。
如果您使用地图的高度图,则可以使用该数据重置不再可见的雪花。

变换反馈和实例化在OpenGL SuperBible (Fifth Edition)在第12章解释,点精灵在第7章The source code for all examples is available online.为Mac OS X中的示例代码只上升到第7章,but it should be possible to make most of it work.

我找不到什么好在线教程,但代码很好评论。变换反馈示例被称为“植绒”。对于雪花模拟,一个顶点着色器应该足以用于一次更新和重新绘制粒子。

如果你想要很多快速移动的雪,water particles from Nvidia's Cascades Demo(从第114页开始)显示了一个有趣的方法来伪造大量的粒子。

0
#include <stdlib.h> 
#include <GL/gl.h> 
#include <GL/glut.h> 

#define PEATALS_NUMBER 100 
#define X 0 
#define Y 1 
#define ORG_X 2 
#define ORG_Y 3 
#define SIZE 4 
#define GROWING 5 
#define SPEED 5 

struct timeval start; 
unsigned long int last_idle_time; 
GLdouble size=5; 
GLboolean growing=true; 
GLdouble tab[PEATALS_NUMBER][7]; 


unsigned int get_ticks(){ 
    struct timeval now; 
    gettimeofday(&now, NULL); 
    return (now.tv_sec - start.tv_sec) * 1000 + 
     (now.tv_usec - start.tv_usec)/1000; 
} 
void init(){ 
    for(int i=0;i<PEATALS_NUMBER;i++){ 
     tab[i][X]=-300+rand()%600; 
     tab[i][Y]=200+rand()%500; 
     tab[i][ORG_X]=tab[i][X]; 
     tab[i][ORG_Y]=tab[i][Y]; 
     tab[i][SIZE]=1+rand()%9; 
     tab[i][GROWING]=rand()%1; 
     tab[i][SPEED]=rand()%10; 
    } 
} 

void Idle(){   
     unsigned long int time_now = get_ticks(); 
     for(int i=0;i<PEATALS_NUMBER;i++){ 
      tab[i][Y] -= (tab[i][SPEED]+40.0) * (time_now - last_idle_time)/1000.0; 
      if(tab[i][Y]<-200.0)tab[i][Y]=tab[i][ORG_Y]; 
      if(tab[i][SIZE]>5){ 
       tab[i][GROWING]=0; 
      } 
      if(tab[i][SIZE]<1){ 
       tab[i][GROWING]=1; 
      } 
      if(tab[i][GROWING]==1.0){ 
       tab[i][SIZE]+=8.0 * (time_now - last_idle_time)/1000.0; 
       tab[i][X] -= (tab[i][SPEED]+1.0) * (time_now - last_idle_time)/1000.0;  
      } 
      else{ 
       tab[i][SIZE]-=8.0 * (time_now - last_idle_time)/1000.0; 
       tab[i][X] += (tab[i][SPEED]+2.0) * (time_now - last_idle_time)/1000.0;  
      } 
     } 
     last_idle_time = time_now;  
     glutPostRedisplay();  
} 

int main(int argc, char *argv[]) { 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowSize(600, 400); 
    gettimeofday(&start, NULL); 
    init(); 
    // size of window 
    glutCreateWindow(argv[0]); 
    glutIdleFunc(Idle); 
    glEnable(GL_POINT_SMOOTH); 
    glutMainLoop(); 
    return 0; 
}