spriteblast.c revision 32001f49
132001f49Smrg 232001f49Smrg/* Copyright (c) Mark J. Kilgard, 1997. */ 332001f49Smrg 432001f49Smrg/* This program is freely distributable without licensing fees 532001f49Smrg and is provided without guarantee or warrantee expressed or 632001f49Smrg implied. This program is -not- in the public domain. */ 732001f49Smrg 832001f49Smrg/* This example demonstrates how to render particle effects 932001f49Smrg with OpenGL. A cloud of pinkish/orange particles explodes with the 1032001f49Smrg particles bouncing off the ground. When the EXT_point_parameters 1132001f49Smrg is present , the particle size is attenuated based on eye distance. */ 1232001f49Smrg 1332001f49Smrg 1432001f49Smrg/* Modified by Brian Paul to test GL_ARB_point_sprite */ 1532001f49Smrg 1632001f49Smrg 1732001f49Smrg#include <assert.h> 1832001f49Smrg#include <stdio.h> 1932001f49Smrg#include <stdlib.h> 2032001f49Smrg#include <string.h> 2132001f49Smrg#include <math.h> /* for cos(), sin(), and sqrt() */ 2232001f49Smrg#ifdef _WIN32 2332001f49Smrg#include <windows.h> 2432001f49Smrg#endif 2532001f49Smrg#include <GL/glew.h> 2632001f49Smrg#include "glut_wrap.h" 2732001f49Smrg 2832001f49Smrg/* Some <math.h> files do not define M_PI... */ 2932001f49Smrg#ifndef M_PI 3032001f49Smrg#define M_PI 3.14159265 3132001f49Smrg#endif 3232001f49Smrg 3332001f49Smrg#if 0 /* For debugging. */ 3432001f49Smrg#undef GL_EXT_point_parameters 3532001f49Smrg#endif 3632001f49Smrg 3732001f49Smrgstatic GLfloat angle = -150; /* in degrees */ 3832001f49Smrgstatic int spin = 0; 3932001f49Smrgstatic int moving, begin; 4032001f49Smrgstatic float theTime; 4132001f49Smrgstatic int repeat = 1; 4232001f49Smrgstatic int blend = 1; 4332001f49Smrgstatic int useMipmaps = 1; 4432001f49Smrgstatic int linearFiltering = 1; 4532001f49Smrg 4632001f49Smrgstatic GLuint Tex0, Tex1; 4732001f49Smrg 4832001f49Smrgstatic GLfloat constant[3] = { .2, 0.0, 0.0 }; 4932001f49Smrgstatic GLfloat linear[3] = { .0, .1, 0.0 }; 5032001f49Smrgstatic GLfloat theQuad[3] = { .005, 0.05, 1/600.0 }; 5132001f49Smrg 5232001f49Smrg#define MAX_POINTS 2000 5332001f49Smrg 5432001f49Smrgstatic int numPoints = 200; 5532001f49Smrg 5632001f49Smrgstatic GLfloat pointList[MAX_POINTS][3]; 5732001f49Smrgstatic GLfloat pointTime[MAX_POINTS]; 5832001f49Smrgstatic GLfloat pointVelocity[MAX_POINTS][2]; 5932001f49Smrgstatic GLfloat pointDirection[MAX_POINTS][2]; 6032001f49Smrgstatic int colorList[MAX_POINTS]; 6132001f49Smrgstatic int animate = 1, motion = 0, org = 0, sprite = 1, smooth = 1; 6232001f49Smrg 6332001f49Smrgstatic GLfloat colorSet[][4] = { 6432001f49Smrg /* Shades of red. */ 6532001f49Smrg { 0.7, 0.2, 0.4, 0.5 }, 6632001f49Smrg { 0.8, 0.0, 0.7, 0.5 }, 6732001f49Smrg { 1.0, 0.0, 0.0, 0.5 }, 6832001f49Smrg { 0.9, 0.3, 0.6, 0.5 }, 6932001f49Smrg { 1.0, 0.4, 0.0, 0.5 }, 7032001f49Smrg { 1.0, 0.0, 0.5, 0.5 }, 7132001f49Smrg}; 7232001f49Smrg 7332001f49Smrg#define NUM_COLORS (sizeof(colorSet)/sizeof(colorSet[0])) 7432001f49Smrg 7532001f49Smrg#define DEAD (NUM_COLORS+1) 7632001f49Smrg 7732001f49Smrg 7832001f49Smrg/* GL */ 7932001f49Smrgstatic GLint spritePattern[16][16] = { 8032001f49Smrg { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 8132001f49Smrg { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 8232001f49Smrg { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 8332001f49Smrg { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, 8432001f49Smrg { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, 8532001f49Smrg { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 }, 8632001f49Smrg { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, 8732001f49Smrg { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, 8832001f49Smrg { 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0 }, 8932001f49Smrg { 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0 }, 9032001f49Smrg { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 }, 9132001f49Smrg { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0 }, 9232001f49Smrg { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0 }, 9332001f49Smrg { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 9432001f49Smrg { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 9532001f49Smrg { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 9632001f49Smrg}; 9732001f49Smrg 9832001f49Smrg 9932001f49Smrg/** Fragment shader which inverts the texture's color */ 10032001f49Smrgstatic const char *FragShaderText = 10132001f49Smrg "uniform sampler2D tex; \n" 10232001f49Smrg "void main(void) \n" 10332001f49Smrg "{ \n" 10432001f49Smrg " gl_FragColor = vec4(1.0) - texture2D(tex, gl_TexCoord[0].xy); \n" 10532001f49Smrg "} \n"; 10632001f49Smrg 10732001f49Smrgstatic GLuint FragShader, ShaderProg; 10832001f49Smrgstatic GLboolean UseFragShader = GL_FALSE; 10932001f49Smrgstatic GLboolean HaveShaders = GL_FALSE; 11032001f49Smrg 11132001f49Smrgstatic void 11232001f49SmrgmakeFragShader(void) 11332001f49Smrg{ 11432001f49Smrg GLint stat; 11532001f49Smrg 11632001f49Smrg HaveShaders = GLEW_VERSION_2_0; 11732001f49Smrg if (!HaveShaders) 11832001f49Smrg return; 11932001f49Smrg 12032001f49Smrg FragShader = glCreateShader(GL_FRAGMENT_SHADER); 12132001f49Smrg glShaderSource(FragShader, 1, (const GLchar **) &FragShaderText, NULL); 12232001f49Smrg glCompileShader(FragShader); 12332001f49Smrg 12432001f49Smrg ShaderProg = glCreateProgram(); 12532001f49Smrg glAttachShader(ShaderProg, FragShader); 12632001f49Smrg glLinkProgram(ShaderProg); 12732001f49Smrg 12832001f49Smrg glGetProgramiv(ShaderProg, GL_LINK_STATUS, &stat); 12932001f49Smrg assert(stat); 13032001f49Smrg} 13132001f49Smrg 13232001f49Smrg 13332001f49Smrg 13432001f49Smrg 13532001f49Smrg#if 0 /* drand48 might be better on Unix machines */ 13632001f49Smrg#define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * drand48()) 13732001f49Smrg#else 13832001f49Smrgstatic float float_rand(void) { return rand() / (float) RAND_MAX; } 13932001f49Smrg#define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * float_rand()) 14032001f49Smrg#endif 14132001f49Smrg 14232001f49Smrg#define MEAN_VELOCITY 3.0 14332001f49Smrg#define GRAVITY 2.0 14432001f49Smrg 14532001f49Smrg/* Modeling units of ground extent in each X and Z direction. */ 14632001f49Smrg#define EDGE 12 14732001f49Smrg 14832001f49Smrgstatic void 14932001f49SmrgmakePointList(void) 15032001f49Smrg{ 15132001f49Smrg float angle, velocity, direction; 15232001f49Smrg int i; 15332001f49Smrg 15432001f49Smrg motion = 1; 15532001f49Smrg for (i=0; i<numPoints; i++) { 15632001f49Smrg pointList[i][0] = 0.0; 15732001f49Smrg pointList[i][1] = 0.0; 15832001f49Smrg pointList[i][2] = 0.0; 15932001f49Smrg pointTime[i] = 0.0; 16032001f49Smrg angle = (RANDOM_RANGE(60.0, 70.0)) * M_PI/180.0; 16132001f49Smrg direction = RANDOM_RANGE(0.0, 360.0) * M_PI/180.0; 16232001f49Smrg pointDirection[i][0] = cos(direction); 16332001f49Smrg pointDirection[i][1] = sin(direction); 16432001f49Smrg velocity = MEAN_VELOCITY + RANDOM_RANGE(-0.8, 1.0); 16532001f49Smrg pointVelocity[i][0] = velocity * cos(angle); 16632001f49Smrg pointVelocity[i][1] = velocity * sin(angle); 16732001f49Smrg colorList[i] = rand() % NUM_COLORS; 16832001f49Smrg } 16932001f49Smrg theTime = 0.0; 17032001f49Smrg} 17132001f49Smrg 17232001f49Smrgstatic void 17332001f49SmrgupdatePointList(void) 17432001f49Smrg{ 17532001f49Smrg float distance; 17632001f49Smrg int i; 17732001f49Smrg 17832001f49Smrg static double t0 = -1.; 17932001f49Smrg double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 18032001f49Smrg if (t0 < 0.0) 18132001f49Smrg t0 = t; 18232001f49Smrg dt = t - t0; 18332001f49Smrg t0 = t; 18432001f49Smrg 18532001f49Smrg motion = 0; 18632001f49Smrg for (i=0; i<numPoints; i++) { 18732001f49Smrg distance = pointVelocity[i][0] * theTime; 18832001f49Smrg 18932001f49Smrg /* X and Z */ 19032001f49Smrg pointList[i][0] = pointDirection[i][0] * distance; 19132001f49Smrg pointList[i][2] = pointDirection[i][1] * distance; 19232001f49Smrg 19332001f49Smrg /* Z */ 19432001f49Smrg pointList[i][1] = 19532001f49Smrg (pointVelocity[i][1] - 0.5 * GRAVITY * pointTime[i])*pointTime[i]; 19632001f49Smrg 19732001f49Smrg /* If we hit the ground, bounce the point upward again. */ 19832001f49Smrg if (pointList[i][1] <= 0.0) { 19932001f49Smrg if (distance > EDGE) { 20032001f49Smrg /* Particle has hit ground past the distance duration of 20132001f49Smrg the particles. Mark particle as dead. */ 20232001f49Smrg colorList[i] = NUM_COLORS; /* Not moving. */ 20332001f49Smrg continue; 20432001f49Smrg } 20532001f49Smrg 20632001f49Smrg pointVelocity[i][1] *= 0.8; /* 80% of previous up velocity. */ 20732001f49Smrg pointTime[i] = 0.0; /* Reset the particles sense of up time. */ 20832001f49Smrg } 20932001f49Smrg motion = 1; 21032001f49Smrg pointTime[i] += dt; 21132001f49Smrg } 21232001f49Smrg theTime += dt; 21332001f49Smrg if (!motion && !spin) { 21432001f49Smrg if (repeat) { 21532001f49Smrg makePointList(); 21632001f49Smrg } else { 21732001f49Smrg glutIdleFunc(NULL); 21832001f49Smrg } 21932001f49Smrg } 22032001f49Smrg} 22132001f49Smrg 22232001f49Smrgstatic void 22332001f49Smrgidle(void) 22432001f49Smrg{ 22532001f49Smrg updatePointList(); 22632001f49Smrg if (spin) { 22732001f49Smrg angle += 0.3; 22832001f49Smrg } 22932001f49Smrg glutPostRedisplay(); 23032001f49Smrg} 23132001f49Smrg 23232001f49Smrgstatic void 23332001f49Smrgvisible(int vis) 23432001f49Smrg{ 23532001f49Smrg if (vis == GLUT_VISIBLE) { 23632001f49Smrg if (animate && (motion || spin)) { 23732001f49Smrg glutIdleFunc(idle); 23832001f49Smrg } 23932001f49Smrg } else { 24032001f49Smrg glutIdleFunc(NULL); 24132001f49Smrg } 24232001f49Smrg} 24332001f49Smrg 24432001f49Smrgstatic void 24532001f49Smrgredraw(void) 24632001f49Smrg{ 24732001f49Smrg int i; 24832001f49Smrg 24932001f49Smrg glDepthMask(GL_TRUE); 25032001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 25132001f49Smrg 25232001f49Smrg if (HaveShaders) 25332001f49Smrg glUseProgram(0); 25432001f49Smrg 25532001f49Smrg glPushMatrix(); 25632001f49Smrg glRotatef(15.0, 1.0, 0.0, 0.0); 25732001f49Smrg glRotatef(angle, 0.0, 1.0, 0.0); 25832001f49Smrg 25932001f49Smrg 26032001f49Smrg /* Draw the floor. */ 26132001f49Smrg glColor3f(0.1, 0.5, 1.0); 26232001f49Smrg glBegin(GL_QUADS); 26332001f49Smrg glTexCoord2f(0.0, 0.0); 26432001f49Smrg glVertex3f(-EDGE, -0.05, -EDGE); 26532001f49Smrg glTexCoord2f(20.0, 0.0); 26632001f49Smrg glVertex3f(EDGE, -0.05, -EDGE); 26732001f49Smrg glTexCoord2f(20.0, 20.0); 26832001f49Smrg glVertex3f(EDGE, -0.05, EDGE); 26932001f49Smrg glTexCoord2f(0.0, 20.0); 27032001f49Smrg glVertex3f(-EDGE, -0.05, EDGE); 27132001f49Smrg glEnd(); 27232001f49Smrg 27332001f49Smrg /* Allow particles to blend with each other. */ 27432001f49Smrg glDepthMask(GL_FALSE); 27532001f49Smrg 27632001f49Smrg if (blend) 27732001f49Smrg glEnable(GL_BLEND); 27832001f49Smrg 27932001f49Smrg if (sprite) { 28032001f49Smrg glActiveTexture(GL_TEXTURE0); 28132001f49Smrg glEnable(GL_TEXTURE_2D); 28232001f49Smrg if (0) { 28332001f49Smrg /* debug/test code */ 28432001f49Smrg glActiveTexture(GL_TEXTURE1); 28532001f49Smrg glEnable(GL_TEXTURE_2D); 28632001f49Smrg } 28732001f49Smrg 28832001f49Smrg#ifdef GL_ARB_point_sprite 28932001f49Smrg glEnable(GL_POINT_SPRITE_ARB); 29032001f49Smrg#endif 29132001f49Smrg if (UseFragShader) { 29232001f49Smrg glUseProgram(ShaderProg); 29332001f49Smrg } 29432001f49Smrg } 29532001f49Smrg 29632001f49Smrg glColor3f(1,1,1); 29732001f49Smrg glBegin(GL_POINTS); 29832001f49Smrg for (i=0; i<numPoints; i++) { 29932001f49Smrg /* Draw alive particles. */ 30032001f49Smrg if (colorList[i] != DEAD) { 30132001f49Smrg if (!sprite) 30232001f49Smrg glColor4fv(colorSet[colorList[i]]); 30332001f49Smrg glVertex3fv(pointList[i]); 30432001f49Smrg } 30532001f49Smrg } 30632001f49Smrg glEnd(); 30732001f49Smrg 30832001f49Smrg glActiveTexture(GL_TEXTURE0); 30932001f49Smrg glDisable(GL_TEXTURE_2D); 31032001f49Smrg glActiveTexture(GL_TEXTURE1); 31132001f49Smrg glDisable(GL_TEXTURE_2D); 31232001f49Smrg 31332001f49Smrg#ifdef GL_ARB_point_sprite 31432001f49Smrg glDisable(GL_POINT_SPRITE_ARB); 31532001f49Smrg#endif 31632001f49Smrg glDisable(GL_BLEND); 31732001f49Smrg 31832001f49Smrg glPopMatrix(); 31932001f49Smrg 32032001f49Smrg glutSwapBuffers(); 32132001f49Smrg} 32232001f49Smrg 32332001f49Smrg/* ARGSUSED2 */ 32432001f49Smrgstatic void 32532001f49Smrgmouse(int button, int state, int x, int y) 32632001f49Smrg{ 32732001f49Smrg /* Scene can be spun around Y axis using left 32832001f49Smrg mouse button movement. */ 32932001f49Smrg if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { 33032001f49Smrg moving = 1; 33132001f49Smrg begin = x; 33232001f49Smrg } 33332001f49Smrg if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { 33432001f49Smrg moving = 0; 33532001f49Smrg } 33632001f49Smrg} 33732001f49Smrg 33832001f49Smrg/* ARGSUSED1 */ 33932001f49Smrgstatic void 34032001f49SmrgmouseMotion(int x, int y) 34132001f49Smrg{ 34232001f49Smrg if (moving) { 34332001f49Smrg angle = angle + (x - begin); 34432001f49Smrg begin = x; 34532001f49Smrg glutPostRedisplay(); 34632001f49Smrg } 34732001f49Smrg} 34832001f49Smrg 34932001f49Smrgstatic void 35032001f49Smrgmenu(int option) 35132001f49Smrg{ 35232001f49Smrg switch (option) { 35332001f49Smrg case 0: 35432001f49Smrg makePointList(); 35532001f49Smrg break; 35632001f49Smrg#ifdef GL_ARB_point_parameters 35732001f49Smrg case 1: 35832001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, constant); 35932001f49Smrg break; 36032001f49Smrg case 2: 36132001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, linear); 36232001f49Smrg break; 36332001f49Smrg case 3: 36432001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad); 36532001f49Smrg break; 36632001f49Smrg#endif 36732001f49Smrg case 4: 36832001f49Smrg blend = 1; 36932001f49Smrg break; 37032001f49Smrg case 5: 37132001f49Smrg blend = 0; 37232001f49Smrg break; 37332001f49Smrg#ifdef GL_ARB_point_parameters 37432001f49Smrg case 6: 37532001f49Smrg glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0); 37632001f49Smrg break; 37732001f49Smrg case 7: 37832001f49Smrg glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 10.0); 37932001f49Smrg break; 38032001f49Smrg#endif 38132001f49Smrg case 8: 38232001f49Smrg glEnable(GL_POINT_SMOOTH); 38332001f49Smrg smooth = 1; 38432001f49Smrg break; 38532001f49Smrg case 9: 38632001f49Smrg glDisable(GL_POINT_SMOOTH); 38732001f49Smrg smooth = 0; 38832001f49Smrg break; 38932001f49Smrg case 10: 39032001f49Smrg glPointSize(16.0); 39132001f49Smrg break; 39232001f49Smrg case 11: 39332001f49Smrg glPointSize(32.0); 39432001f49Smrg break; 39532001f49Smrg case 12: 39632001f49Smrg glPointSize(64.0); 39732001f49Smrg break; 39832001f49Smrg case 13: 39932001f49Smrg spin = 1 - spin; 40032001f49Smrg if (animate && (spin || motion)) { 40132001f49Smrg glutIdleFunc(idle); 40232001f49Smrg } else { 40332001f49Smrg glutIdleFunc(NULL); 40432001f49Smrg } 40532001f49Smrg break; 40632001f49Smrg case 14: 40732001f49Smrg numPoints = 200; 40832001f49Smrg break; 40932001f49Smrg case 15: 41032001f49Smrg numPoints = 500; 41132001f49Smrg break; 41232001f49Smrg case 16: 41332001f49Smrg numPoints = 1000; 41432001f49Smrg break; 41532001f49Smrg case 17: 41632001f49Smrg numPoints = 2000; 41732001f49Smrg break; 41832001f49Smrg case 666: 41932001f49Smrg exit(0); 42032001f49Smrg } 42132001f49Smrg glutPostRedisplay(); 42232001f49Smrg} 42332001f49Smrg 42432001f49Smrg/* ARGSUSED1 */ 42532001f49Smrgstatic void 42632001f49Smrgkey(unsigned char c, int x, int y) 42732001f49Smrg{ 42832001f49Smrg switch (c) { 42932001f49Smrg case 13: 43032001f49Smrg animate = 1 - animate; /* toggle. */ 43132001f49Smrg if (animate && (motion || spin)) { 43232001f49Smrg glutIdleFunc(idle); 43332001f49Smrg } else { 43432001f49Smrg glutIdleFunc(NULL); 43532001f49Smrg } 43632001f49Smrg break; 43732001f49Smrg case ' ': 43832001f49Smrg animate = 1; 43932001f49Smrg makePointList(); 44032001f49Smrg glutIdleFunc(idle); 44132001f49Smrg break; 44232001f49Smrg case 'o': 44332001f49Smrg case 'O': 44432001f49Smrg org ^= 1; 44532001f49Smrg#ifdef GL_VERSION_2_0 44632001f49Smrg#ifdef GL_ARB_point_parameters 44732001f49Smrg glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, 44832001f49Smrg org ? GL_LOWER_LEFT : GL_UPPER_LEFT); 44932001f49Smrg#endif 45032001f49Smrg#endif 45132001f49Smrg glutPostRedisplay(); 45232001f49Smrg break; 45332001f49Smrg case 't': 45432001f49Smrg case 'T': 45532001f49Smrg sprite ^= 1; 45632001f49Smrg glutPostRedisplay(); 45732001f49Smrg break; 45832001f49Smrg case 's': 45932001f49Smrg case 'S': 46032001f49Smrg (smooth ^= 1) ? glEnable(GL_POINT_SMOOTH) : glDisable(GL_POINT_SMOOTH); 46132001f49Smrg glutPostRedisplay(); 46232001f49Smrg break; 46332001f49Smrg case 'f': 46432001f49Smrg case 'F': 46532001f49Smrg if (HaveShaders) { 46632001f49Smrg UseFragShader = !UseFragShader; 46732001f49Smrg glutPostRedisplay(); 46832001f49Smrg } 46932001f49Smrg break; 47032001f49Smrg case '0': 47132001f49Smrg glPointSize(1.0); 47232001f49Smrg glutPostRedisplay(); 47332001f49Smrg break; 47432001f49Smrg case '1': 47532001f49Smrg glPointSize(16.0); 47632001f49Smrg glutPostRedisplay(); 47732001f49Smrg break; 47832001f49Smrg case '2': 47932001f49Smrg glPointSize(32.0); 48032001f49Smrg glutPostRedisplay(); 48132001f49Smrg break; 48232001f49Smrg case '3': 48332001f49Smrg glPointSize(64.0); 48432001f49Smrg glutPostRedisplay(); 48532001f49Smrg break; 48632001f49Smrg case '4': 48732001f49Smrg glPointSize(128.0); 48832001f49Smrg glutPostRedisplay(); 48932001f49Smrg break; 49032001f49Smrg case 27: 49132001f49Smrg exit(0); 49232001f49Smrg } 49332001f49Smrg} 49432001f49Smrg 49532001f49Smrg 49632001f49Smrg 49732001f49Smrgstatic void 49832001f49SmrgmakeSpriteTextures(void) 49932001f49Smrg{ 50032001f49Smrg GLubyte texture[16][16][4]; 50132001f49Smrg int i, j; 50232001f49Smrg 50332001f49Smrg if (!glutExtensionSupported("GL_ARB_point_sprite")) { 50432001f49Smrg printf("Sorry, this demo requires GL_ARB_point_sprite.\n"); 50532001f49Smrg exit(0); 50632001f49Smrg } 50732001f49Smrg if (!glutExtensionSupported("GL_ARB_point_parameters")) { 50832001f49Smrg printf("Sorry, this demo requires GL_ARB_point_parameters.\n"); 50932001f49Smrg exit(0); 51032001f49Smrg } 51132001f49Smrg 51232001f49Smrg /* "GL" */ 51332001f49Smrg for (i = 0; i < 16; i++) { 51432001f49Smrg for (j = 0; j < 16; j++) { 51532001f49Smrg if (spritePattern[i][j]) { 51632001f49Smrg texture[i][j][0] = 255; 51732001f49Smrg texture[i][j][1] = 255; 51832001f49Smrg texture[i][j][2] = 255; 51932001f49Smrg texture[i][j][3] = 255; 52032001f49Smrg } 52132001f49Smrg else { 52232001f49Smrg texture[i][j][0] = 255; 52332001f49Smrg texture[i][j][1] = 0; 52432001f49Smrg texture[i][j][2] = 0; 52532001f49Smrg texture[i][j][3] = 0; 52632001f49Smrg } 52732001f49Smrg } 52832001f49Smrg } 52932001f49Smrg 53032001f49Smrg /* texture 0 */ 53132001f49Smrg glActiveTexture(GL_TEXTURE0); 53232001f49Smrg glGenTextures(1, &Tex0); 53332001f49Smrg glBindTexture(GL_TEXTURE_2D, Tex0); 53432001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, 53532001f49Smrg texture); 53632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 53732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 53832001f49Smrg 53932001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 54032001f49Smrg#ifdef GL_ARB_point_sprite 54132001f49Smrg glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); 54232001f49Smrg#endif 54332001f49Smrg 54432001f49Smrg /* left=yellow, right=green */ 54532001f49Smrg memset(texture, 0, sizeof(texture)); 54632001f49Smrg for (i = 0; i < 16; i++) { 54732001f49Smrg for (j = 0; j < 16; j++) { 54832001f49Smrg if (j < 8) { 54932001f49Smrg texture[i][j][0] = 255; 55032001f49Smrg texture[i][j][1] = 255; 55132001f49Smrg texture[i][j][2] = 0; 55232001f49Smrg texture[i][j][3] = 255; 55332001f49Smrg } 55432001f49Smrg else { 55532001f49Smrg texture[i][j][0] = 0; 55632001f49Smrg texture[i][j][1] = 255; 55732001f49Smrg texture[i][j][2] = 0; 55832001f49Smrg texture[i][j][3] = 255; 55932001f49Smrg } 56032001f49Smrg } 56132001f49Smrg } 56232001f49Smrg 56332001f49Smrg /* texture 1 */ 56432001f49Smrg glActiveTexture(GL_TEXTURE1); 56532001f49Smrg glGenTextures(1, &Tex1); 56632001f49Smrg glBindTexture(GL_TEXTURE_2D, Tex1); 56732001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, 56832001f49Smrg texture); 56932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 57032001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 57132001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 57232001f49Smrg#ifdef GL_ARB_point_sprite 57332001f49Smrg glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); 57432001f49Smrg#endif 57532001f49Smrg 57632001f49Smrg glActiveTexture(GL_TEXTURE0); 57732001f49Smrg} 57832001f49Smrg 57932001f49Smrg 58032001f49Smrgstatic void 58132001f49Smrgreshape(int width, int height) 58232001f49Smrg{ 58332001f49Smrg GLfloat h = (GLfloat) height / (GLfloat) width; 58432001f49Smrg 58532001f49Smrg glViewport(0, 0, (GLint) width, (GLint) height); 58632001f49Smrg 58732001f49Smrg#if 0 /* debug/test code */ 58832001f49Smrg glMatrixMode(GL_TEXTURE); 58932001f49Smrg glLoadIdentity(); 59032001f49Smrg glRotatef(45, 0, 0, 1); 59132001f49Smrg#endif 59232001f49Smrg 59332001f49Smrg glMatrixMode(GL_PROJECTION); 59432001f49Smrg glLoadIdentity(); 59532001f49Smrg glFrustum(-1.0, 1.0, -h, h, 2.0, 30.0); 59632001f49Smrg glMatrixMode(GL_MODELVIEW); 59732001f49Smrg glLoadIdentity(); 59832001f49Smrg glTranslatef(0.0, 0.0, -10.0); 59932001f49Smrg} 60032001f49Smrg 60132001f49Smrgint 60232001f49Smrgmain(int argc, char **argv) 60332001f49Smrg{ 60432001f49Smrg int i; 60532001f49Smrg 60632001f49Smrg glutInitWindowSize(600,300); 60732001f49Smrg glutInit(&argc, argv); 60832001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); 60932001f49Smrg 61032001f49Smrg for (i=1; i<argc; i++) { 61132001f49Smrg if(!strcmp("-noms", argv[i])) { 61232001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 61332001f49Smrg printf("forcing no multisampling\n"); 61432001f49Smrg } else if(!strcmp("-nomipmaps", argv[i])) { 61532001f49Smrg useMipmaps = 0; 61632001f49Smrg } else if(!strcmp("-nearest", argv[i])) { 61732001f49Smrg linearFiltering = 0; 61832001f49Smrg } 61932001f49Smrg } 62032001f49Smrg glutCreateWindow("sprite blast"); 62132001f49Smrg glewInit(); 62232001f49Smrg glutReshapeFunc(reshape); 62332001f49Smrg glutDisplayFunc(redraw); 62432001f49Smrg glutMouseFunc(mouse); 62532001f49Smrg glutMotionFunc(mouseMotion); 62632001f49Smrg glutVisibilityFunc(visible); 62732001f49Smrg glutKeyboardFunc(key); 62832001f49Smrg glutCreateMenu(menu); 62932001f49Smrg glutAddMenuEntry("Reset time", 0); 63032001f49Smrg glutAddMenuEntry("Constant", 1); 63132001f49Smrg glutAddMenuEntry("Linear", 2); 63232001f49Smrg glutAddMenuEntry("Quadratic", 3); 63332001f49Smrg glutAddMenuEntry("Blend on", 4); 63432001f49Smrg glutAddMenuEntry("Blend off", 5); 63532001f49Smrg glutAddMenuEntry("Threshold 1", 6); 63632001f49Smrg glutAddMenuEntry("Threshold 10", 7); 63732001f49Smrg glutAddMenuEntry("Point smooth on", 8); 63832001f49Smrg glutAddMenuEntry("Point smooth off", 9); 63932001f49Smrg glutAddMenuEntry("Point size 16", 10); 64032001f49Smrg glutAddMenuEntry("Point size 32", 11); 64132001f49Smrg glutAddMenuEntry("Point size 64", 12); 64232001f49Smrg glutAddMenuEntry("Toggle spin", 13); 64332001f49Smrg glutAddMenuEntry("200 points ", 14); 64432001f49Smrg glutAddMenuEntry("500 points ", 15); 64532001f49Smrg glutAddMenuEntry("1000 points ", 16); 64632001f49Smrg glutAddMenuEntry("2000 points ", 17); 64732001f49Smrg glutAddMenuEntry("Quit", 666); 64832001f49Smrg glutAttachMenu(GLUT_RIGHT_BUTTON); 64932001f49Smrg 65032001f49Smrg makePointList(); 65132001f49Smrg makeSpriteTextures(); 65232001f49Smrg makeFragShader(); 65332001f49Smrg 65432001f49Smrg glShadeModel(GL_FLAT); 65532001f49Smrg glEnable(GL_DEPTH_TEST); 65632001f49Smrg glEnable(GL_POINT_SMOOTH); 65732001f49Smrg glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 65832001f49Smrg glPointSize(32.0); 65932001f49Smrg#ifdef GL_ARB_point_parameters 66032001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad); 66132001f49Smrg#endif 66232001f49Smrg 66332001f49Smrg glutMainLoop(); 66432001f49Smrg return 0; /* ANSI C requires main to return int. */ 66532001f49Smrg} 666