Симуляция снежного покрова в OpenGL? - PullRequest
0 голосов
/ 01 августа 2011

Я хочу сделать анимацию для снежинок, используя OpenGL.Может кто-нибудь предложить мне учебник или пример кода?

Ответы [ 3 ]

2 голосов
/ 05 августа 2011

Вы можете использовать преобразование обратной связи для расчета физики частиц в вершинном шейдере и установление , если вы хотите использовать трехмерные снежинки. Точечные спрайты должны сделать рекламные щиты быстрее и использовать меньше памяти для хранения вершин. (Вам нужен только один на снежинку.)

Запуск системы частиц в вершинном шейдере сделает ее в несколько раз быстрее, в то время как математика практически не изменится.

Вы также можете использовать 3D-текстуру, чтобы компенсировать расчет демпфирования, чтобы иметь видимые турбулентности.
Если вы используете карту высот для земли, вы можете использовать эти данные для сброса снежинок, которые больше не видны.

Обратная связь и создание экземпляров преобразования описаны в OpenGL SuperBible (пятое издание) в главе 12, точечные спрайты - в главе 7. Исходный код для всех примеров доступен в Интернете. Пример кода для Mac OS X подходит только к главе 7, , но большая часть его должна работать.

Я не смог найти хороших онлайн-учебников, но код хорошо прокомментирован. Пример обратной связи с преобразованием называется «флокирование». Для симуляции снежинки одного вершинного шейдера должно быть достаточно как для обновления, так и для рендеринга частиц за один проход.

Если вам нужно много быстро движущегося снега, частицы воды из демонстрации каскадов Nvidia (начиная со страницы 114) демонстрируют интересный подход к подделке большого количества частиц.

2 голосов
/ 01 августа 2011

Одним из возможных решений является использование системы частиц .Однажды я сделал из этого несколько эффектов взрыва, и я думаю, что это довольно близко к тому, что вы хотите.

Вот одно из руководств, которые я использовал , и я думаю, что это может быть полезно (кстатина этом сайте есть много хороших учебных пособий, вы можете их проверить).

Кроме того, для генерации снежных хлопьев вы можете просто использовать идентичные хлопья, но если вы хотите более причудливые вещи (не слишком причудливые, ноотносительно легко), вы можете использовать треугольные полосы (которые используются в учебном пособии) для достижения лучшего эффекта, так как снежные хлопья симметричны.

0 голосов
/ 19 декабря 2014
#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...