2
/* Copyright (c) Mark J. Kilgard, 1997. */
4
/* This program is freely distributable without licensing fees
5
and is provided without guarantee or warrantee expressed or
6
implied. This program is -not- in the public domain. */
8
/* This example demonstrates how to render particle effects
9
with OpenGL. A cloud of pinkish/orange particles explodes with the
10
particles bouncing off the ground. When the EXT_point_parameters
11
is present , the particle size is attenuated based on eye distance. */
14
/* Modified by Brian Paul to test GL_ARB_point_sprite */
20
#include <math.h> /* for cos(), sin(), and sqrt() */
24
#define GL_GLEXT_PROTOTYPES
27
/* Some <math.h> files do not define M_PI... */
29
#define M_PI 3.14159265
32
#if 0 /* For debugging. */
33
#undef GL_EXT_point_parameters
36
static GLfloat angle = -150; /* in degrees */
38
static int moving, begin;
40
static int repeat = 1;
43
int linearFiltering = 1;
45
static GLfloat constant[3] = { .2, 0.0, 0.0 };
46
static GLfloat linear[3] = { .0, .1, 0.0 };
47
static GLfloat theQuad[3] = { .005, 0.1, 1/600.0 };
49
#define MAX_POINTS 2000
51
static int numPoints = 200;
53
static GLfloat pointList[MAX_POINTS][3];
54
static GLfloat pointTime[MAX_POINTS];
55
static GLfloat pointVelocity[MAX_POINTS][2];
56
static GLfloat pointDirection[MAX_POINTS][2];
57
static int colorList[MAX_POINTS];
58
static int animate = 1, motion = 0, org = 0, sprite = 1, smooth = 1;
60
static GLfloat colorSet[][4] = {
62
{ 0.7, 0.2, 0.4, 0.5 },
63
{ 0.8, 0.0, 0.7, 0.5 },
64
{ 1.0, 0.0, 0.0, 0.5 },
65
{ 0.9, 0.3, 0.6, 0.5 },
66
{ 1.0, 0.4, 0.0, 0.5 },
67
{ 1.0, 0.0, 0.5, 0.5 },
70
#define NUM_COLORS (sizeof(colorSet)/sizeof(colorSet[0]))
72
#define DEAD (NUM_COLORS+1)
76
static GLint spritePattern[16][16] = {
77
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
78
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
79
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
80
{ 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
81
{ 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
82
{ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 },
83
{ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
84
{ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
85
{ 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0 },
86
{ 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0 },
87
{ 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 },
88
{ 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0 },
89
{ 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0 },
90
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
91
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
92
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
98
#if 0 /* drand48 might be better on Unix machines */
99
#define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * drand48())
101
static float float_rand(void) { return rand() / (float) RAND_MAX; }
102
#define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * float_rand())
105
#define MEAN_VELOCITY 3.0
108
/* Modeling units of ground extent in each X and Z direction. */
114
float angle, velocity, direction;
118
for (i=0; i<numPoints; i++) {
119
pointList[i][0] = 0.0;
120
pointList[i][1] = 0.0;
121
pointList[i][2] = 0.0;
123
angle = (RANDOM_RANGE(60.0, 70.0)) * M_PI/180.0;
124
direction = RANDOM_RANGE(0.0, 360.0) * M_PI/180.0;
125
pointDirection[i][0] = cos(direction);
126
pointDirection[i][1] = sin(direction);
127
velocity = MEAN_VELOCITY + RANDOM_RANGE(-0.8, 1.0);
128
pointVelocity[i][0] = velocity * cos(angle);
129
pointVelocity[i][1] = velocity * sin(angle);
130
colorList[i] = rand() % NUM_COLORS;
136
updatePointList(void)
141
static double t0 = -1.;
142
double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
149
for (i=0; i<numPoints; i++) {
150
distance = pointVelocity[i][0] * theTime;
153
pointList[i][0] = pointDirection[i][0] * distance;
154
pointList[i][2] = pointDirection[i][1] * distance;
158
(pointVelocity[i][1] - 0.5 * GRAVITY * pointTime[i])*pointTime[i];
160
/* If we hit the ground, bounce the point upward again. */
161
if (pointList[i][1] <= 0.0) {
162
if (distance > EDGE) {
163
/* Particle has hit ground past the distance duration of
164
the particles. Mark particle as dead. */
165
colorList[i] = NUM_COLORS; /* Not moving. */
169
pointVelocity[i][1] *= 0.8; /* 80% of previous up velocity. */
170
pointTime[i] = 0.0; /* Reset the particles sense of up time. */
176
if (!motion && !spin) {
198
if (vis == GLUT_VISIBLE) {
199
if (animate && (motion || spin)) {
212
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
215
glRotatef(15.0, 1.0, 0.0, 0.0);
216
glRotatef(angle, 0.0, 1.0, 0.0);
218
glDepthMask(GL_FALSE);
220
/* Draw the floor. */
221
/* glEnable(GL_TEXTURE_2D);*/
222
glColor3f(0.1, 0.5, 1.0);
224
glTexCoord2f(0.0, 0.0);
225
glVertex3f(-EDGE, -0.05, -EDGE);
226
glTexCoord2f(20.0, 0.0);
227
glVertex3f(EDGE, -0.05, -EDGE);
228
glTexCoord2f(20.0, 20.0);
229
glVertex3f(EDGE, -0.05, EDGE);
230
glTexCoord2f(0.0, 20.0);
231
glVertex3f(-EDGE, -0.05, EDGE);
234
/* Allow particles to blend with each other. */
235
glDepthMask(GL_TRUE);
241
glEnable(GL_TEXTURE_2D);
242
#ifdef GL_ARB_point_sprite
243
glEnable(GL_POINT_SPRITE_ARB);
249
for (i=0; i<numPoints; i++) {
250
/* Draw alive particles. */
251
if (colorList[i] != DEAD) {
252
if (!sprite) glColor4fv(colorSet[colorList[i]]);
253
glVertex3fv(pointList[i]);
258
glDisable(GL_TEXTURE_2D);
259
#ifdef GL_ARB_point_sprite
260
glDisable(GL_POINT_SPRITE_ARB);
271
mouse(int button, int state, int x, int y)
273
/* Scene can be spun around Y axis using left
274
mouse button movement. */
275
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
279
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
286
mouseMotion(int x, int y)
289
angle = angle + (x - begin);
302
#ifdef GL_ARB_point_parameters
304
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, constant);
307
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, linear);
310
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad);
319
#ifdef GL_ARB_point_parameters
321
glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0);
324
glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 10.0);
328
glEnable(GL_POINT_SMOOTH);
332
glDisable(GL_POINT_SMOOTH);
346
if (animate && (spin || motion)) {
372
key(unsigned char c, int x, int y)
376
animate = 1 - animate; /* toggle. */
377
if (animate && (motion || spin)) {
391
#ifdef GL_VERSION_2_0
392
#ifdef GL_ARB_point_parameters
393
glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN,
394
org ? GL_LOWER_LEFT : GL_UPPER_LEFT);
406
(smooth ^= 1) ? glEnable(GL_POINT_SMOOTH) : glDisable(GL_POINT_SMOOTH);
439
GLubyte texture[16][16][4];
442
if (!glutExtensionSupported("GL_ARB_point_sprite")) {
443
printf("Sorry, this demo requires GL_ARB_point_sprite.\n");
446
if (!glutExtensionSupported("GL_ARB_point_parameters")) {
447
printf("Sorry, this demo requires GL_ARB_point_parameters.\n");
451
for (i = 0; i < 16; i++) {
452
for (j = 0; j < 16; j++) {
453
if (spritePattern[i][j]) {
454
texture[i][j][0] = 255;
455
texture[i][j][1] = 255;
456
texture[i][j][2] = 255;
457
texture[i][j][3] = 255;
460
texture[i][j][0] = 255;
461
texture[i][j][1] = 0;
462
texture[i][j][2] = 0;
463
texture[i][j][3] = 0;
468
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
470
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
471
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
472
#ifdef GL_ARB_point_sprite
473
glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
479
reshape(int width, int height)
481
GLfloat h = (GLfloat) height / (GLfloat) width;
483
glViewport(0, 0, (GLint) width, (GLint) height);
484
glMatrixMode(GL_PROJECTION);
486
glFrustum(-1.0, 1.0, -h, h, 2.0, 30.0);
487
glMatrixMode(GL_MODELVIEW);
489
glTranslatef(0.0, 0.0, -10.0);
493
main(int argc, char **argv)
496
glutInit(&argc, argv);
497
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
499
for (i=1; i<argc; i++) {
500
if(!strcmp("-noms", argv[i])) {
501
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
502
printf("forcing no multisampling\n");
503
} else if(!strcmp("-nomipmaps", argv[i])) {
505
} else if(!strcmp("-nearest", argv[i])) {
509
glutInitWindowPosition(0, 0);
510
glutInitWindowSize(600,300);
511
glutCreateWindow("sprite blast");
512
glutReshapeFunc(reshape);
513
glutDisplayFunc(redraw);
514
glutMouseFunc(mouse);
515
glutMotionFunc(mouseMotion);
516
glutVisibilityFunc(visible);
517
glutKeyboardFunc(key);
518
glutCreateMenu(menu);
519
glutAddMenuEntry("Reset time", 0);
520
glutAddMenuEntry("Constant", 1);
521
glutAddMenuEntry("Linear", 2);
522
glutAddMenuEntry("Quadratic", 3);
523
glutAddMenuEntry("Blend on", 4);
524
glutAddMenuEntry("Blend off", 5);
525
glutAddMenuEntry("Threshold 1", 6);
526
glutAddMenuEntry("Threshold 10", 7);
527
glutAddMenuEntry("Point smooth on", 8);
528
glutAddMenuEntry("Point smooth off", 9);
529
glutAddMenuEntry("Point size 4", 10);
530
glutAddMenuEntry("Point size 8", 11);
531
glutAddMenuEntry("Point size 16", 12);
532
glutAddMenuEntry("Toggle spin", 13);
533
glutAddMenuEntry("200 points ", 14);
534
glutAddMenuEntry("500 points ", 15);
535
glutAddMenuEntry("1000 points ", 16);
536
glutAddMenuEntry("2000 points ", 17);
537
glutAddMenuEntry("Quit", 666);
538
glutAttachMenu(GLUT_RIGHT_BUTTON);
543
glShadeModel(GL_FLAT);
544
glEnable(GL_DEPTH_TEST);
545
glEnable(GL_POINT_SMOOTH);
546
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
548
#ifdef GL_ARB_point_parameters
549
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad);
553
return 0; /* ANSI C requires main to return int. */