我是靠谱客的博主 神勇秀发,最近开发中收集的这篇文章主要介绍windows visual studio 基于openGL的粒子系统设计,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

这是我上计算机三维动画的时候的期末作业,自己动手做的能实现粒子系统的效果,同时代码很简单,

只有一个cpp文件,很适合想要理解粒子系统原理的童鞋,童鞋可以拷贝代码修改,从而加深粒子系统的概念理解

所以的东西均为原创,希望自己能写出更多的简单而又全的例子帮大家更好的理解计算机的中很多看似复杂的东西

希望大家多多支持我

首先上效果图


下面是代码,带有注释(PS:如果环境不会配置的童鞋可以查看我博客的另外的文章,有专门描述如何搭建windows visual studio openGL的开发环境)

stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//


#pragma once


#include <windows.h>
#include "targetver.h"
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <gl/GLU.h>
#include <gl/GL.h>
#include <gl/glut.h>


// TODO: 在此处引用程序需要的其他头文件



MMParcticle.cpp

#include "stdafx.h"


#define MAX_PARTICLES 500
#define RANDX rand()%20-10.0f // 粒子发射器X轴随机位置
#define RANDZ rand()%20-10.0f //粒子发射器Z轴随机位置


// 粒子系统参数
float emmiterY = 10.0f;
float emmiterX = 0.0f;
float emmiterZ = 0.0f;


float slowdown = 1.0f; // 加速减速因子
float xSpeed;
float ySpeed;
float zoom = -10.0f;


GLuint loop;
GLuint col;
GLuint delay;


// 相机移动参数
float angle = 0.0f;
float lx=0.0f,lz=-1.0f;
// XZ position of the camera
float x=0.0f,z=5.0f;


// 粒子的结构体
typedef struct
{
bool active;  // 是否处于激活状态
float life; // 生命值
float fade; // 生命值衰减速度
// 颜色
float r; 
float g;
float b;
// 位置
float x;
float y;
float z;
// 速度矢量
float xi;
float yi;
float zi;
// 加速度矢量
float xg;
float yg;
float zg;
}particles;


// 粒子数组
particles particle[MAX_PARTICLES];
// 粒子颜色
static GLfloat colors[12][3]=
{
{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
{0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
{0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}
};


// 纹理创建
#define checkImageWidth 4
#define checkImageHeight 4
static GLubyte checkImage[checkImageHeight][checkImageWidth][4];
// 纹理唯一ID索引
static GLuint texName;


// 用于载入纹理(目前尚未使用)
void makeCheckImage(void)
{
int i, j, c;


for (i = 0; i < checkImageHeight; i++) {
for (j = 0; j < checkImageWidth; j++) {
//c = ((((i&0x8)==0)^((j&0x8))==0))*255;
checkImage[i][j][0] = (GLubyte) 255;
checkImage[i][j][1] = (GLubyte) 255;
checkImage[i][j][2] = (GLubyte) 255;
checkImage[i][j][3] = (GLubyte) 255;
}
}

}


void init(void)
{    
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
makeCheckImage();


// 生成一个纹理对象
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &texName); 
glBindTexture(GL_TEXTURE_2D, texName); 


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_NEAREST);


// 载入纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, 
checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 
checkImage);


// 初始化粒子
for (loop=0; loop<MAX_PARTICLES; loop++)
{
particle[loop].active = true;
particle[loop].life = 1.0f;
particle[loop].fade=float(rand()%100)/1000.0f+0.003f;
particle[loop].r=colors[loop*(12/MAX_PARTICLES)][0];
particle[loop].g=colors[loop*(12/MAX_PARTICLES)][1];
particle[loop].b=colors[loop*(12/MAX_PARTICLES)][2];
particle[loop].xi=float((rand()%50)-26.0f)*10.0f;
particle[loop].yi=float((rand()%50)-25.0f)*10.0f;
particle[loop].zi=float((rand()%50)-25.0f)*10.0f;
particle[loop].xg=0.0f;
particle[loop].yg=-0.8f;
particle[loop].zg=0.0f;
// 粒子发射器位置
particle[loop].y=emmiterY;
particle[loop].x = float(RANDX);
particle[loop].z = float(RANDZ);
}
}


// openGL 主循环绘制函数
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt( x, 1.0f, z,
x+lx, 1.0f,  z+lz,
0.0f, 1.0f,  0.0f);


// 画地面
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f,  100.0f);
glVertex3f( 100.0f, 0.0f,  100.0f);
glVertex3f( 100.0f, 0.0f, -100.0f);
glEnd();




glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texName); 


// 遍历所有的粒子,让粒子随着时间的变化而移动
for (loop=0;loop<MAX_PARTICLES;loop++)
{
if (particle[loop].active)
{
float x=particle[loop].x;
float y=particle[loop].y;
float z=particle[loop].z+zoom;


glColor4f(particle[loop].r,particle[loop].g,particle[loop].b,particle[loop].life);
// 带有纹理的粒子系统
/* glBegin(GL_TRIANGLE_STRIP);

glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z); 
glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z);
glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z);
glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z);
glEnd()*/;


// Draw Head
glPushMatrix();
glTranslatef(x+0.5f,y+0.5f,z);
glutSolidSphere(0.10f,10,10);
glPopMatrix();


// 粒子位置变化
particle[loop].x+=particle[loop].xi/(slowdown*1000);
particle[loop].y+=particle[loop].yi/(slowdown*1000);
particle[loop].z+=particle[loop].zi/(slowdown*1000);


// 粒子速度的变化
particle[loop].xi+=particle[loop].xg;
particle[loop].yi+=particle[loop].yg;
particle[loop].zi+=particle[loop].zg;


// 粒子生命的变化
particle[loop].life-=particle[loop].fade;


// 如果粒子生命结束,将生命结束的粒子从新移动到发射位置
if (particle[loop].life<0.0f)
{
particle[loop].life=1.0f;
particle[loop].fade=float(rand()%100)/1000.0f+0.003f;

// 将粒子从新放回粒子发射器位置
particle[loop].y=emmiterY;
particle[loop].x = float(RANDX);
particle[loop].z = float(RANDZ);


particle[loop].xi=xSpeed+float((rand()%60)-32.0f);
particle[loop].yi=ySpeed+float((rand()%60)-30.0f);
particle[loop].zi=float((rand()%60)-30.0f);


particle[loop].r=colors[col][0];
particle[loop].g=colors[col][1];
particle[loop].b=colors[col][2];




}
}
}

glFlush();
glDisable(GL_TEXTURE_2D);
}


// 处理openGL放大缩小之后的视点矩阵的变化
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.6);
}


// 处理键盘事件
void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
default:
break;
}
}


// 键盘按钮控制相机的移动
void MMprocessSpecialKeys(int key, int xx, int yy) {


float fraction = 0.1f;


switch (key) {
//只是改变了视点坐标向量,没有移动相机
case GLUT_KEY_LEFT : 
angle -= 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
//只是改变了视点坐标向量,没有移动相机
case GLUT_KEY_RIGHT :
angle += 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
// 没有改变视点,改变了相机的位置
case GLUT_KEY_UP :
x += lx * fraction;
z += lz * fraction;
break;
// 没有改变视点,改变了相机的位置
case GLUT_KEY_DOWN :
x -= lx * fraction;
z -= lz * fraction;
break;
}
}


int main(int argc, char** argv)
{
// opengl 初始化的代码
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(250, 250);
glutInitWindowPosition(100, 100);
glutCreateWindow("穆洪:简单粒子系统");


// 粒子系统初始化工作
init();
glutDisplayFunc(DrawGLScene);
glutIdleFunc(DrawGLScene);
// 处理部分特殊按键
glutSpecialFunc(MMprocessSpecialKeys);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
// openGL主循环
glutMainLoop();
return 0; 
}

最后

以上就是神勇秀发为你收集整理的windows visual studio 基于openGL的粒子系统设计的全部内容,希望文章能够帮你解决windows visual studio 基于openGL的粒子系统设计所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部