2011-08-01 115 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; 
}