132001f49Smrg/*
232001f49Smrg * Draw the "fire" test program on the six faces of a cube using
332001f49Smrg * fbo render-to-texture.
432001f49Smrg *
532001f49Smrg * Much of the code comes from David Bucciarelli's "fire"
632001f49Smrg * test program. The rest basically from Brian Paul's "gearbox" and
732001f49Smrg * fbotexture programs.
832001f49Smrg *
932001f49Smrg * By pressing the 'q' key, you can make the driver choose different
1032001f49Smrg * internal texture RGBA formats by giving it different "format" and "type"
1132001f49Smrg * arguments to the glTexImage2D function that creates the texture
1232001f49Smrg * image being rendered to. If the driver doesn't support a texture image
1332001f49Smrg * format as a render target, it will usually fall back to software when
1432001f49Smrg * drawing the "fire" image, and frame-rate should drop considerably.
1532001f49Smrg *
1632001f49Smrg * Performance:
1732001f49Smrg * The rendering speed of this program is usually dictated by fill rate
1832001f49Smrg * and the fact that software fallbacks for glBitMap makes the driver
1932001f49Smrg * operate synchronously. Low-end UMA hardware will probably see around
2032001f49Smrg * 35 fps with the help screen disabled and 32bpp window- and user
2132001f49Smrg * frame-buffers (2008).
2232001f49Smrg *
2332001f49Smrg * This program is released under GPL, following the "fire" licensing.
2432001f49Smrg *
2532001f49Smrg * Authors:
2632001f49Smrg *   David Bucciarelli ("fire")
2732001f49Smrg *   Brian Paul ("gearbox", "fbotexture")
2832001f49Smrg *   Thomas Hellstrom (Putting it together)
2932001f49Smrg *
3032001f49Smrg */
3132001f49Smrg
3232001f49Smrg#include <math.h>
3332001f49Smrg#include <stdlib.h>
3432001f49Smrg#include <stdio.h>
3532001f49Smrg#include <string.h>
3632001f49Smrg#include <GL/glew.h>
3732001f49Smrg#include "glut_wrap.h"
3832001f49Smrg#include "readtex.h"
3932001f49Smrg
4032001f49Smrg
4132001f49Smrg/*
4232001f49Smrg * Format of texture we render to.
4332001f49Smrg */
4432001f49Smrg
4532001f49Smrg#define TEXINTFORMAT GL_RGBA
4632001f49Smrg
4732001f49Smrgstatic GLuint texTypes[] =
4832001f49Smrg   {GL_UNSIGNED_BYTE,
4932001f49Smrg    GL_UNSIGNED_INT_8_8_8_8_REV,
5032001f49Smrg    GL_UNSIGNED_SHORT_1_5_5_5_REV,
5132001f49Smrg    GL_UNSIGNED_SHORT_4_4_4_4_REV,
5232001f49Smrg    GL_UNSIGNED_INT_8_8_8_8,
5332001f49Smrg    GL_UNSIGNED_SHORT_5_5_5_1,
5432001f49Smrg    GL_UNSIGNED_SHORT_4_4_4_4,
5532001f49Smrg    GL_UNSIGNED_INT_8_8_8_8_REV,
5632001f49Smrg    GL_UNSIGNED_SHORT_1_5_5_5_REV,
5732001f49Smrg    GL_UNSIGNED_SHORT_4_4_4_4_REV,
5832001f49Smrg    GL_UNSIGNED_INT_8_8_8_8,
5932001f49Smrg    GL_UNSIGNED_SHORT_5_5_5_1,
6032001f49Smrg    GL_UNSIGNED_SHORT_4_4_4_4,
6132001f49Smrg    GL_UNSIGNED_SHORT_5_6_5,
6232001f49Smrg    GL_UNSIGNED_SHORT_5_6_5_REV,
6332001f49Smrg    GL_UNSIGNED_SHORT_5_6_5,
6432001f49Smrg    GL_UNSIGNED_SHORT_5_6_5_REV};
6532001f49Smrg
6632001f49Smrgstatic GLuint texFormats[] =
6732001f49Smrg   {GL_RGBA,
6832001f49Smrg    GL_RGBA,
6932001f49Smrg    GL_RGBA,
7032001f49Smrg    GL_RGBA,
7132001f49Smrg    GL_RGBA,
7232001f49Smrg    GL_RGBA,
7332001f49Smrg    GL_RGBA,
7432001f49Smrg    GL_BGRA,
7532001f49Smrg    GL_BGRA,
7632001f49Smrg    GL_BGRA,
7732001f49Smrg    GL_BGRA,
7832001f49Smrg    GL_BGRA,
7932001f49Smrg    GL_BGRA,
8032001f49Smrg    GL_RGB,
8132001f49Smrg    GL_RGB,
8232001f49Smrg    GL_BGR,
8332001f49Smrg    GL_BGR};
8432001f49Smrg
8532001f49Smrgstatic const char *texNames[] =
8632001f49Smrg   {"GL_RGBA GL_UNSIGNED_BYTE",
8732001f49Smrg    "GL_RGBA GL_UNSIGNED_INT_8_8_8_8_REV",
8832001f49Smrg    "GL_RGBA GL_UNSIGNED_SHORT_1_5_5_5_REV",
8932001f49Smrg    "GL_RGBA GL_UNSIGNED_SHORT_4_4_4_4_REV",
9032001f49Smrg    "GL_RGBA GL_UNSIGNED_INT_8_8_8_8",
9132001f49Smrg    "GL_RGBA GL_UNSIGNED_INT_5_5_5_1",
9232001f49Smrg    "GL_RGBA GL_UNSIGNED_INT_4_4_4_4",
9332001f49Smrg    "GL_BGRA GL_UNSIGNED_INT_8_8_8_8_REV",
9432001f49Smrg    "GL_BGRA GL_UNSIGNED_SHORT_1_5_5_5_REV",
9532001f49Smrg    "GL_BGRA GL_UNSIGNED_SHORT_4_4_4_4_REV",
9632001f49Smrg    "GL_BGRA GL_UNSIGNED_INT_8_8_8_8",
9732001f49Smrg    "GL_BGRA GL_UNSIGNED_INT_5_5_5_1",
9832001f49Smrg    "GL_BGRA GL_UNSIGNED_INT_4_4_4_4",
9932001f49Smrg    "GL_RGB GL_UNSIGNED_INT_5_6_5",
10032001f49Smrg    "GL_RGB GL_UNSIGNED_INT_5_6_5_REV",
10132001f49Smrg    "GL_BGR GL_UNSIGNED_INT_5_6_5",
10232001f49Smrg    "GL_BGR GL_UNSIGNED_INT_5_6_5_REV"};
10332001f49Smrg
10432001f49Smrg
10532001f49Smrg
10632001f49Smrg
10732001f49Smrg#ifndef M_PI
10832001f49Smrg#define M_PI 3.1415926535
10932001f49Smrg#endif
11032001f49Smrg
11132001f49Smrg#define vinit(a,i,j,k) {			\
11232001f49Smrg      (a)[0]=i;					\
11332001f49Smrg      (a)[1]=j;					\
11432001f49Smrg      (a)[2]=k;					\
11532001f49Smrg   }
11632001f49Smrg
11732001f49Smrg#define vinit4(a,i,j,k,w) {			\
11832001f49Smrg      (a)[0]=i;					\
11932001f49Smrg      (a)[1]=j;					\
12032001f49Smrg      (a)[2]=k;					\
12132001f49Smrg      (a)[3]=w;					\
12232001f49Smrg   }
12332001f49Smrg
12432001f49Smrg
12532001f49Smrg#define vadds(a,dt,b) {				\
12632001f49Smrg      (a)[0]+=(dt)*(b)[0];			\
12732001f49Smrg      (a)[1]+=(dt)*(b)[1];			\
12832001f49Smrg      (a)[2]+=(dt)*(b)[2];			\
12932001f49Smrg   }
13032001f49Smrg
13132001f49Smrg#define vequ(a,b) {				\
13232001f49Smrg      (a)[0]=(b)[0];				\
13332001f49Smrg      (a)[1]=(b)[1];				\
13432001f49Smrg      (a)[2]=(b)[2];				\
13532001f49Smrg   }
13632001f49Smrg
13732001f49Smrg#define vinter(a,dt,b,c) {			\
13832001f49Smrg      (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];	\
13932001f49Smrg      (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];	\
14032001f49Smrg      (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];	\
14132001f49Smrg   }
14232001f49Smrg
14332001f49Smrg#define clamp(a)        ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
14432001f49Smrg
14532001f49Smrg#define vclamp(v) {				\
14632001f49Smrg      (v)[0]=clamp((v)[0]);			\
14732001f49Smrg      (v)[1]=clamp((v)[1]);			\
14832001f49Smrg      (v)[2]=clamp((v)[2]);			\
14932001f49Smrg   }
15032001f49Smrg
15132001f49Smrgstatic GLint WinWidth = 800, WinHeight = 800;
15232001f49Smrgstatic GLint TexWidth, TexHeight;
15332001f49Smrgstatic GLuint TexObj;
15432001f49Smrgstatic GLuint MyFB;
15532001f49Smrgstatic GLuint DepthRB;
15632001f49Smrgstatic GLboolean WireFrame = GL_FALSE;
15732001f49Smrgstatic GLboolean Anim = GL_TRUE;
15832001f49Smrgstatic GLint texType = 0;
15932001f49Smrg
16032001f49Smrgstatic GLint T0 = 0;
16132001f49Smrgstatic GLint Frames = 0;
16232001f49Smrgstatic GLint Win = 0;
16332001f49Smrg
16432001f49Smrgstatic GLfloat ViewRotX = 20.0, ViewRotY = 30.0, ViewRotZ = 0.0;
16532001f49Smrgstatic GLfloat CubeRot = 0.0;
16632001f49Smrg
16732001f49Smrg
16832001f49Smrgstatic void
16932001f49Smrgidle(void);
17032001f49Smrg
17132001f49Smrg
17232001f49Smrgstatic void
17332001f49SmrgCheckError(int line)
17432001f49Smrg{
17532001f49Smrg   GLenum err = glGetError();
17632001f49Smrg   if (err) {
17732001f49Smrg      printf("GL Error 0x%x at line %d\n", (int) err, line);
17832001f49Smrg      exit(1);
17932001f49Smrg   }
18032001f49Smrg}
18132001f49Smrg
18232001f49Smrg
18332001f49Smrgstatic void
18432001f49Smrgcleanup(void)
18532001f49Smrg{
18632001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
18732001f49Smrg   glDeleteFramebuffersEXT(1, &MyFB);
18832001f49Smrg   glDeleteRenderbuffersEXT(1, &DepthRB);
18932001f49Smrg   glDeleteTextures(1, &TexObj);
19032001f49Smrg   glutDestroyWindow(Win);
19132001f49Smrg}
19232001f49Smrg
19332001f49Smrgstatic GLint NiceFog = 1;
19432001f49Smrg
19532001f49Smrg#define DIMP 20.0
19632001f49Smrg#define DIMTP 16.0
19732001f49Smrg
19832001f49Smrg#define RIDCOL 0.4
19932001f49Smrg
20032001f49Smrg#define NUMTREE 50
20132001f49Smrg#define TREEINR 2.5
20232001f49Smrg#define TREEOUTR 8.0
20332001f49Smrg
20432001f49Smrg#define AGRAV -9.8
20532001f49Smrg
20632001f49Smrgtypedef struct
20732001f49Smrg{
20832001f49Smrg   int age;
20932001f49Smrg   float p[3][3];
21032001f49Smrg   float v[3];
21132001f49Smrg   float c[3][4];
21232001f49Smrg}
21332001f49Smrg   part;
21432001f49Smrg
21532001f49Smrgstatic float treepos[NUMTREE][3];
21632001f49Smrg
21732001f49Smrgstatic float black[3] = { 0.0, 0.0, 0.0 };
21832001f49Smrgstatic float blu[3] = { 1.0, 0.2, 0.0 };
21932001f49Smrgstatic float blu2[3] = { 1.0, 1.0, 0.0 };
22032001f49Smrg
22132001f49Smrgstatic float fogcolor[4] = { 1.0, 1.0, 1.0, 1.0 };
22232001f49Smrg
22332001f49Smrgstatic float q[4][3] = {
22432001f49Smrg   {-DIMP, 0.0, -DIMP},
22532001f49Smrg   {DIMP, 0.0, -DIMP},
22632001f49Smrg   {DIMP, 0.0, DIMP},
22732001f49Smrg   {-DIMP, 0.0, DIMP}
22832001f49Smrg};
22932001f49Smrg
23032001f49Smrgstatic float qt[4][2] = {
23132001f49Smrg   {-DIMTP, -DIMTP},
23232001f49Smrg   {DIMTP, -DIMTP},
23332001f49Smrg   {DIMTP, DIMTP},
23432001f49Smrg   {-DIMTP, DIMTP}
23532001f49Smrg};
23632001f49Smrg
23732001f49Smrgstatic int np;
23832001f49Smrgstatic float eject_r, dt, maxage, eject_vy, eject_vl;
23932001f49Smrgstatic short shadows;
24032001f49Smrgstatic float ridtri;
24132001f49Smrgstatic int fog = 0;
24232001f49Smrgstatic int help = 1;
24332001f49Smrg
24432001f49Smrgstatic part *p;
24532001f49Smrg
24632001f49Smrgstatic GLuint groundid;
24732001f49Smrgstatic GLuint treeid;
24832001f49Smrg
24932001f49Smrgstatic float obs[3] = { 2.0, 1.0, 0.0 };
25032001f49Smrgstatic float dir[3];
25132001f49Smrgstatic float v = 0.0;
25232001f49Smrgstatic float alpha = -84.0;
25332001f49Smrgstatic float beta = 90.0;
25432001f49Smrg
25532001f49Smrgstatic float
25632001f49Smrgvrnd(void)
25732001f49Smrg{
25832001f49Smrg   return (((float) rand()) / RAND_MAX);
25932001f49Smrg}
26032001f49Smrg
26132001f49Smrgstatic void
26232001f49Smrgsetnewpart(part * p)
26332001f49Smrg{
26432001f49Smrg   float a, v[3], *c;
26532001f49Smrg
26632001f49Smrg   p->age = 0;
26732001f49Smrg
26832001f49Smrg   a = vrnd() * 3.14159265359 * 2.0;
26932001f49Smrg
27032001f49Smrg   vinit(v, sin(a) * eject_r * vrnd(), 0.15, cos(a) * eject_r * vrnd());
27132001f49Smrg   vinit(p->p[0], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
27232001f49Smrg	 v[2] + vrnd() * ridtri);
27332001f49Smrg   vinit(p->p[1], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
27432001f49Smrg	 v[2] + vrnd() * ridtri);
27532001f49Smrg   vinit(p->p[2], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
27632001f49Smrg	 v[2] + vrnd() * ridtri);
27732001f49Smrg
27832001f49Smrg   vinit(p->v, v[0] * eject_vl / (eject_r / 2),
27932001f49Smrg	 vrnd() * eject_vy + eject_vy / 2, v[2] * eject_vl / (eject_r / 2));
28032001f49Smrg
28132001f49Smrg   c = blu;
28232001f49Smrg
28332001f49Smrg   vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
28432001f49Smrg	  c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
28532001f49Smrg	  c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
28632001f49Smrg   vinit4(p->c[1], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
28732001f49Smrg	  c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
28832001f49Smrg	  c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
28932001f49Smrg   vinit4(p->c[2], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
29032001f49Smrg	  c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
29132001f49Smrg	  c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
29232001f49Smrg}
29332001f49Smrg
29432001f49Smrgstatic void
29532001f49Smrgsetpart(part * p)
29632001f49Smrg{
29732001f49Smrg   float fact;
29832001f49Smrg
29932001f49Smrg   if (p->p[0][1] < 0.1) {
30032001f49Smrg      setnewpart(p);
30132001f49Smrg      return;
30232001f49Smrg   }
30332001f49Smrg
30432001f49Smrg   p->v[1] += AGRAV * dt;
30532001f49Smrg
30632001f49Smrg   vadds(p->p[0], dt, p->v);
30732001f49Smrg   vadds(p->p[1], dt, p->v);
30832001f49Smrg   vadds(p->p[2], dt, p->v);
30932001f49Smrg
31032001f49Smrg   p->age++;
31132001f49Smrg
31232001f49Smrg   if ((p->age) > maxage) {
31332001f49Smrg      vequ(p->c[0], blu2);
31432001f49Smrg      vequ(p->c[1], blu2);
31532001f49Smrg      vequ(p->c[2], blu2);
31632001f49Smrg   }
31732001f49Smrg   else {
31832001f49Smrg      fact = 1.0 / maxage;
31932001f49Smrg      vadds(p->c[0], fact, blu2);
32032001f49Smrg      vclamp(p->c[0]);
32132001f49Smrg      p->c[0][3] = fact * (maxage - p->age);
32232001f49Smrg
32332001f49Smrg      vadds(p->c[1], fact, blu2);
32432001f49Smrg      vclamp(p->c[1]);
32532001f49Smrg      p->c[1][3] = fact * (maxage - p->age);
32632001f49Smrg
32732001f49Smrg      vadds(p->c[2], fact, blu2);
32832001f49Smrg      vclamp(p->c[2]);
32932001f49Smrg      p->c[2][3] = fact * (maxage - p->age);
33032001f49Smrg   }
33132001f49Smrg}
33232001f49Smrg
33332001f49Smrgstatic void
33432001f49Smrgdrawtree(float x, float y, float z)
33532001f49Smrg{
33632001f49Smrg   glBegin(GL_QUADS);
33732001f49Smrg   glTexCoord2f(0.0, 0.0);
33832001f49Smrg   glVertex3f(x - 1.5, y + 0.0, z);
33932001f49Smrg
34032001f49Smrg   glTexCoord2f(1.0, 0.0);
34132001f49Smrg   glVertex3f(x + 1.5, y + 0.0, z);
34232001f49Smrg
34332001f49Smrg   glTexCoord2f(1.0, 1.0);
34432001f49Smrg   glVertex3f(x + 1.5, y + 3.0, z);
34532001f49Smrg
34632001f49Smrg   glTexCoord2f(0.0, 1.0);
34732001f49Smrg   glVertex3f(x - 1.5, y + 3.0, z);
34832001f49Smrg
34932001f49Smrg
35032001f49Smrg   glTexCoord2f(0.0, 0.0);
35132001f49Smrg   glVertex3f(x, y + 0.0, z - 1.5);
35232001f49Smrg
35332001f49Smrg   glTexCoord2f(1.0, 0.0);
35432001f49Smrg   glVertex3f(x, y + 0.0, z + 1.5);
35532001f49Smrg
35632001f49Smrg   glTexCoord2f(1.0, 1.0);
35732001f49Smrg   glVertex3f(x, y + 3.0, z + 1.5);
35832001f49Smrg
35932001f49Smrg   glTexCoord2f(0.0, 1.0);
36032001f49Smrg   glVertex3f(x, y + 3.0, z - 1.5);
36132001f49Smrg
36232001f49Smrg   glEnd();
36332001f49Smrg
36432001f49Smrg}
36532001f49Smrg
36632001f49Smrgstatic void
36732001f49Smrgcalcposobs(void)
36832001f49Smrg{
36932001f49Smrg   dir[0] = sin(alpha * M_PI / 180.0);
37032001f49Smrg   dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
37132001f49Smrg   dir[1] = cos(beta * M_PI / 180.0);
37232001f49Smrg
37332001f49Smrg   if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
37432001f49Smrg      dir[0] = 0;
37532001f49Smrg   if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
37632001f49Smrg      dir[1] = 0;
37732001f49Smrg   if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
37832001f49Smrg      dir[2] = 0;
37932001f49Smrg
38032001f49Smrg   obs[0] += v * dir[0];
38132001f49Smrg   obs[1] += v * dir[1];
38232001f49Smrg   obs[2] += v * dir[2];
38332001f49Smrg}
38432001f49Smrg
38532001f49Smrgstatic void
38632001f49Smrgprintstring(void *font, const char *string)
38732001f49Smrg{
38832001f49Smrg   int len, i;
38932001f49Smrg
39032001f49Smrg   len = (int) strlen(string);
39132001f49Smrg   for (i = 0; i < len; i++)
39232001f49Smrg      glutBitmapCharacter(font, string[i]);
39332001f49Smrg}
39432001f49Smrg
39532001f49Smrg
39632001f49Smrgstatic void
39732001f49Smrgprinthelp(void)
39832001f49Smrg{
39932001f49Smrg   glColor4f(0.0, 0.0, 0.0, 0.5);
40032001f49Smrg   glRecti(40, 40, 600, 440);
40132001f49Smrg
40232001f49Smrg   glColor3f(1.0, 0.0, 0.0);
40332001f49Smrg   glRasterPos2i(300, 420);
40432001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
40532001f49Smrg
40632001f49Smrg   glRasterPos2i(60, 390);
40732001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
40832001f49Smrg
40932001f49Smrg   glRasterPos2i(60, 360);
41032001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Increase particle size");
41132001f49Smrg   glRasterPos2i(60, 330);
41232001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "T - Decrease particle size");
41332001f49Smrg
41432001f49Smrg   glRasterPos2i(60, 300);
41532001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "r - Increase emission radius");
41632001f49Smrg   glRasterPos2i(60, 270);
41732001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "R - Decrease emission radius");
41832001f49Smrg
41932001f49Smrg   glRasterPos2i(60, 240);
42032001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
42132001f49Smrg   glRasterPos2i(60, 210);
42232001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "s - Toggle shadows");
42332001f49Smrg   glRasterPos2i(60, 180);
42432001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "q - Toggle texture format & type");
42532001f49Smrg   glRasterPos2i(60, 150);
42632001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
42732001f49Smrg   glRasterPos2i(60, 120);
42832001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
42932001f49Smrg   glRasterPos2i(60, 90);
43032001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24,  "Arrow Keys - Rotate");
43132001f49Smrg}
43232001f49Smrg
43332001f49Smrg
43432001f49Smrgstatic void
43532001f49Smrgdrawfire(void)
43632001f49Smrg{
43732001f49Smrg   static char frbuf[80] = "";
43832001f49Smrg   int j;
43932001f49Smrg   static double t0 = -1.;
44032001f49Smrg   double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
44132001f49Smrg   if (t0 < 0.0)
44232001f49Smrg      t0 = t;
44332001f49Smrg   dt = (t - t0) * 1.0;
44432001f49Smrg   t0 = t;
44532001f49Smrg
44632001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
44732001f49Smrg
44832001f49Smrg   glDisable(GL_LIGHTING);
44932001f49Smrg
45032001f49Smrg   glShadeModel(GL_FLAT);
45132001f49Smrg
45232001f49Smrg   glEnable(GL_BLEND);
45332001f49Smrg   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
45432001f49Smrg
45532001f49Smrg   glEnable(GL_FOG);
45632001f49Smrg   glFogi(GL_FOG_MODE, GL_EXP);
45732001f49Smrg   glFogfv(GL_FOG_COLOR, fogcolor);
45832001f49Smrg   glFogf(GL_FOG_DENSITY, 0.1);
45932001f49Smrg
46032001f49Smrg
46132001f49Smrg   glViewport(0, 0, (GLint) TexWidth, (GLint) TexHeight);
46232001f49Smrg   glMatrixMode(GL_PROJECTION);
46332001f49Smrg   glLoadIdentity();
46432001f49Smrg   gluPerspective(70.0, TexWidth/ (float) TexHeight, 0.1, 30.0);
46532001f49Smrg
46632001f49Smrg   glMatrixMode(GL_MODELVIEW);
46732001f49Smrg   glLoadIdentity();
46832001f49Smrg
46932001f49Smrg   if (NiceFog)
47032001f49Smrg      glHint(GL_FOG_HINT, GL_NICEST);
47132001f49Smrg   else
47232001f49Smrg      glHint(GL_FOG_HINT, GL_DONT_CARE);
47332001f49Smrg
47432001f49Smrg   glEnable(GL_DEPTH_TEST);
47532001f49Smrg
47632001f49Smrg   if (fog)
47732001f49Smrg      glEnable(GL_FOG);
47832001f49Smrg   else
47932001f49Smrg      glDisable(GL_FOG);
48032001f49Smrg
48132001f49Smrg   glDepthMask(GL_TRUE);
48232001f49Smrg   glClearColor(1.0, 1.0, 1.0, 1.0);
48332001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
48432001f49Smrg
48532001f49Smrg
48632001f49Smrg   glPushMatrix();
48732001f49Smrg   calcposobs();
48832001f49Smrg   gluLookAt(obs[0], obs[1], obs[2],
48932001f49Smrg	     obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
49032001f49Smrg	     0.0, 1.0, 0.0);
49132001f49Smrg
49232001f49Smrg   glColor4f(1.0, 1.0, 1.0, 1.0);
49332001f49Smrg
49432001f49Smrg   glEnable(GL_TEXTURE_2D);
49532001f49Smrg
49632001f49Smrg   glBindTexture(GL_TEXTURE_2D, groundid);
49732001f49Smrg   glBegin(GL_QUADS);
49832001f49Smrg   glTexCoord2fv(qt[0]);
49932001f49Smrg   glVertex3fv(q[0]);
50032001f49Smrg   glTexCoord2fv(qt[1]);
50132001f49Smrg   glVertex3fv(q[1]);
50232001f49Smrg   glTexCoord2fv(qt[2]);
50332001f49Smrg   glVertex3fv(q[2]);
50432001f49Smrg   glTexCoord2fv(qt[3]);
50532001f49Smrg   glVertex3fv(q[3]);
50632001f49Smrg   glEnd();
50732001f49Smrg
50832001f49Smrg   glEnable(GL_ALPHA_TEST);
50932001f49Smrg   glAlphaFunc(GL_GEQUAL, 0.9);
51032001f49Smrg
51132001f49Smrg   glBindTexture(GL_TEXTURE_2D, treeid);
51232001f49Smrg   for (j = 0; j < NUMTREE; j++)
51332001f49Smrg      drawtree(treepos[j][0], treepos[j][1], treepos[j][2]);
51432001f49Smrg
51532001f49Smrg   glDisable(GL_TEXTURE_2D);
51632001f49Smrg   glDepthMask(GL_FALSE);
51732001f49Smrg   glDisable(GL_ALPHA_TEST);
51832001f49Smrg
51932001f49Smrg   if (shadows) {
52032001f49Smrg      glBegin(GL_TRIANGLES);
52132001f49Smrg      for (j = 0; j < np; j++) {
52232001f49Smrg	 glColor4f(black[0], black[1], black[2], p[j].c[0][3]);
52332001f49Smrg	 glVertex3f(p[j].p[0][0], 0.1, p[j].p[0][2]);
52432001f49Smrg
52532001f49Smrg	 glColor4f(black[0], black[1], black[2], p[j].c[1][3]);
52632001f49Smrg	 glVertex3f(p[j].p[1][0], 0.1, p[j].p[1][2]);
52732001f49Smrg
52832001f49Smrg	 glColor4f(black[0], black[1], black[2], p[j].c[2][3]);
52932001f49Smrg	 glVertex3f(p[j].p[2][0], 0.1, p[j].p[2][2]);
53032001f49Smrg      }
53132001f49Smrg      glEnd();
53232001f49Smrg   }
53332001f49Smrg
53432001f49Smrg   glBegin(GL_TRIANGLES);
53532001f49Smrg   for (j = 0; j < np; j++) {
53632001f49Smrg      glColor4fv(p[j].c[0]);
53732001f49Smrg      glVertex3fv(p[j].p[0]);
53832001f49Smrg
53932001f49Smrg      glColor4fv(p[j].c[1]);
54032001f49Smrg      glVertex3fv(p[j].p[1]);
54132001f49Smrg
54232001f49Smrg      glColor4fv(p[j].c[2]);
54332001f49Smrg      glVertex3fv(p[j].p[2]);
54432001f49Smrg
54532001f49Smrg      setpart(&p[j]);
54632001f49Smrg   }
54732001f49Smrg   glEnd();
54832001f49Smrg
54932001f49Smrg
55032001f49Smrg   glDisable(GL_TEXTURE_2D);
55132001f49Smrg   glDisable(GL_ALPHA_TEST);
55232001f49Smrg   glDisable(GL_DEPTH_TEST);
55332001f49Smrg   glDisable(GL_FOG);
55432001f49Smrg
55532001f49Smrg   glMatrixMode(GL_PROJECTION);
55632001f49Smrg   glLoadIdentity();
55732001f49Smrg   glOrtho(-0.5, 639.5, -0.5, 479.5
55832001f49Smrg	   , -1.0, 1.0);
55932001f49Smrg   glMatrixMode(GL_MODELVIEW);
56032001f49Smrg   glLoadIdentity();
56132001f49Smrg
56232001f49Smrg   glColor3f(1.0, 0.0, 0.0);
56332001f49Smrg   glRasterPos2i(10, 10);
56432001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
56532001f49Smrg   glColor3f(0.0, 0.0, 1.0);
56632001f49Smrg   glRasterPos2i(10, 450);
56732001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_18, texNames[texType]);
56832001f49Smrg   glColor3f(1.0, 0.0, 0.0);
56932001f49Smrg   glRasterPos2i(10, 470);
57032001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_10,
57132001f49Smrg	       "Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
57232001f49Smrg
57332001f49Smrg   if (help)
57432001f49Smrg      printhelp();
57532001f49Smrg
57632001f49Smrg   glPopMatrix();
57732001f49Smrg   glDepthMask(GL_TRUE);
57832001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
57932001f49Smrg   Frames++;
58032001f49Smrg
58132001f49Smrg   {
58232001f49Smrg      GLint t = glutGet(GLUT_ELAPSED_TIME);
58332001f49Smrg      if (t - T0 >= 2000) {
58432001f49Smrg	 GLfloat seconds = (t - T0) / 1000.0;
58532001f49Smrg	 GLfloat fps = Frames / seconds;
58632001f49Smrg	 sprintf(frbuf, "Frame rate: %f", fps);
5877ec3b29aSmrg	 printf("%s\n", frbuf);
5887ec3b29aSmrg	 fflush(stdout);
58932001f49Smrg	 T0 = t;
59032001f49Smrg	 Frames = 0;
59132001f49Smrg      }
59232001f49Smrg   }
59332001f49Smrg
59432001f49Smrg}
59532001f49Smrg
59632001f49Smrgstatic void
59732001f49Smrgregen_texImage(void)
59832001f49Smrg{
59932001f49Smrg   glBindTexture(GL_TEXTURE_2D, TexObj);
60032001f49Smrg   glTexImage2D(GL_TEXTURE_2D, 0, TEXINTFORMAT, TexWidth, TexHeight, 0,
60132001f49Smrg		texFormats[texType], texTypes[texType], NULL);
60232001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
60332001f49Smrg   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
60432001f49Smrg			     GL_TEXTURE_2D, TexObj, 0);
60532001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
60632001f49Smrg}
60732001f49Smrg
60832001f49Smrgstatic void
60932001f49Smrgkey(unsigned char key, int x, int y)
61032001f49Smrg{
61132001f49Smrg   switch (key) {
61232001f49Smrg   case 27:
61332001f49Smrg      cleanup();
61432001f49Smrg      exit(0);
61532001f49Smrg      break;
61632001f49Smrg   case ' ':
61732001f49Smrg      Anim = !Anim;
61832001f49Smrg      glutIdleFunc(Anim ? idle : NULL);
61932001f49Smrg      break;
62032001f49Smrg   case 'a':
62132001f49Smrg      v += 0.0005;
62232001f49Smrg      break;
62332001f49Smrg   case 'z':
62432001f49Smrg      v -= 0.0005;
62532001f49Smrg      break;
62632001f49Smrg   case 'h':
62732001f49Smrg      help = (!help);
62832001f49Smrg      break;
62932001f49Smrg   case 'f':
63032001f49Smrg      fog = (!fog);
63132001f49Smrg      break;
63232001f49Smrg   case 's':
63332001f49Smrg      shadows = !shadows;
63432001f49Smrg      break;
63532001f49Smrg   case 'R':
63632001f49Smrg      eject_r -= 0.03;
63732001f49Smrg      break;
63832001f49Smrg   case 'r':
63932001f49Smrg      eject_r += 0.03;
64032001f49Smrg      break;
64132001f49Smrg   case 't':
64232001f49Smrg      ridtri += 0.005;
64332001f49Smrg      break;
64432001f49Smrg   case 'T':
64532001f49Smrg      ridtri -= 0.005;
64632001f49Smrg      break;
64732001f49Smrg   case 'v':
64832001f49Smrg      ViewRotZ += 5.0;
64932001f49Smrg      break;
65032001f49Smrg   case 'V':
65132001f49Smrg      ViewRotZ -= 5.0;
65232001f49Smrg      break;
65332001f49Smrg   case 'w':
65432001f49Smrg      WireFrame = !WireFrame;
65532001f49Smrg      break;
65632001f49Smrg   case 'q':
65732001f49Smrg      if (++texType > 16)
65832001f49Smrg	 texType = 0;
65932001f49Smrg      regen_texImage();
66032001f49Smrg      break;
66132001f49Smrg   case 'n':
66232001f49Smrg      NiceFog = !NiceFog;
66332001f49Smrg      printf("NiceFog %d\n", NiceFog);
66432001f49Smrg      break;
66532001f49Smrg   }
66632001f49Smrg   glutPostRedisplay();
66732001f49Smrg}
66832001f49Smrg
66932001f49Smrgstatic void
67032001f49Smrginittextures(void)
67132001f49Smrg{
67232001f49Smrg   GLenum gluerr;
67332001f49Smrg   GLubyte tex[128][128][4];
67432001f49Smrg
67532001f49Smrg   glGenTextures(1, &groundid);
67632001f49Smrg   glBindTexture(GL_TEXTURE_2D, groundid);
67732001f49Smrg
67832001f49Smrg   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
67932001f49Smrg   if (!LoadRGBMipmaps(DEMOS_DATA_DIR "s128.rgb", GL_RGB)) {
68032001f49Smrg      fprintf(stderr, "Error reading a texture.\n");
68132001f49Smrg      exit(-1);
68232001f49Smrg   }
68332001f49Smrg
68432001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
68532001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
68632001f49Smrg
68732001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
68832001f49Smrg		   GL_LINEAR_MIPMAP_LINEAR);
68932001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
69032001f49Smrg
69132001f49Smrg   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
69232001f49Smrg
69332001f49Smrg   glGenTextures(1, &treeid);
69432001f49Smrg   glBindTexture(GL_TEXTURE_2D, treeid);
69532001f49Smrg
69632001f49Smrg   if (1)
69732001f49Smrg      {
69832001f49Smrg	 int w, h;
69932001f49Smrg	 GLenum format;
70032001f49Smrg	 int x, y;
70132001f49Smrg	 GLubyte *image = LoadRGBImage(DEMOS_DATA_DIR "tree3.rgb",
70232001f49Smrg				       &w, &h, &format);
70332001f49Smrg
70432001f49Smrg	 if (!image) {
70532001f49Smrg	    fprintf(stderr, "Error reading a texture.\n");
70632001f49Smrg	    exit(-1);
70732001f49Smrg	 }
70832001f49Smrg
70932001f49Smrg	 for (y = 0; y < 128; y++)
71032001f49Smrg	    for (x = 0; x < 128; x++) {
71132001f49Smrg	       tex[x][y][0] = image[(y + x * 128) * 3];
71232001f49Smrg	       tex[x][y][1] = image[(y + x * 128) * 3 + 1];
71332001f49Smrg	       tex[x][y][2] = image[(y + x * 128) * 3 + 2];
71432001f49Smrg	       if ((tex[x][y][0] == tex[x][y][1]) &&
71532001f49Smrg		   (tex[x][y][1] == tex[x][y][2]) && (tex[x][y][2] == 255))
71632001f49Smrg		  tex[x][y][3] = 0;
71732001f49Smrg	       else
71832001f49Smrg		  tex[x][y][3] = 255;
71932001f49Smrg	    }
72032001f49Smrg
72132001f49Smrg	 if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA,
72232001f49Smrg					 GL_UNSIGNED_BYTE, (GLvoid *) (tex)))) {
72332001f49Smrg	    fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr));
72432001f49Smrg	    exit(-1);
72532001f49Smrg	 }
72632001f49Smrg      }
72732001f49Smrg   else {
72832001f49Smrg      if (!LoadRGBMipmaps(DEMOS_DATA_DIR "tree2.rgba", GL_RGBA)) {
72932001f49Smrg	 fprintf(stderr, "Error reading a texture.\n");
73032001f49Smrg	 exit(-1);
73132001f49Smrg      }
73232001f49Smrg   }
73332001f49Smrg
73432001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
73532001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
73632001f49Smrg
73732001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
73832001f49Smrg		   GL_LINEAR_MIPMAP_LINEAR);
73932001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
74032001f49Smrg
74132001f49Smrg   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
74232001f49Smrg}
74332001f49Smrg
74432001f49Smrgstatic void
74532001f49Smrginittree(void)
74632001f49Smrg{
74732001f49Smrg   int i;
74832001f49Smrg   float dist;
74932001f49Smrg
75032001f49Smrg   for (i = 0; i < NUMTREE; i++)
75132001f49Smrg      do {
75232001f49Smrg	 treepos[i][0] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
75332001f49Smrg	 treepos[i][1] = 0.0;
75432001f49Smrg	 treepos[i][2] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
75532001f49Smrg	 dist =
75632001f49Smrg	    sqrt(treepos[i][0] * treepos[i][0] +
75732001f49Smrg		 treepos[i][2] * treepos[i][2]);
75832001f49Smrg      } while ((dist < TREEINR) || (dist > TREEOUTR));
75932001f49Smrg}
76032001f49Smrg
76132001f49Smrgstatic int
76232001f49Smrginit_fire(int ac, char *av[])
76332001f49Smrg{
76432001f49Smrg   int i;
76532001f49Smrg
76632001f49Smrg   np = 800;
76732001f49Smrg   eject_r = -0.65;
76832001f49Smrg   dt = 0.015;
76932001f49Smrg   eject_vy = 4;
77032001f49Smrg   eject_vl = 1;
77132001f49Smrg   shadows = 1;
77232001f49Smrg   ridtri = 0.25;
77332001f49Smrg
77432001f49Smrg   maxage = 1.0 / dt;
77532001f49Smrg
77632001f49Smrg   if (ac == 2)
77732001f49Smrg      np = atoi(av[1]);
77832001f49Smrg
77932001f49Smrg
78032001f49Smrg   inittextures();
78132001f49Smrg
78232001f49Smrg   p = (part *) malloc(sizeof(part) * np);
78332001f49Smrg
78432001f49Smrg   for (i = 0; i < np; i++)
78532001f49Smrg      setnewpart(&p[i]);
78632001f49Smrg
78732001f49Smrg   inittree();
78832001f49Smrg
78932001f49Smrg   return (0);
79032001f49Smrg}
79132001f49Smrg
79232001f49Smrg
79332001f49Smrg
79432001f49Smrg
79532001f49Smrg
79632001f49Smrg
79732001f49Smrgstatic void
79832001f49SmrgDrawCube(void)
79932001f49Smrg{
80032001f49Smrg   static const GLfloat texcoords[4][2] = {
80132001f49Smrg      { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
80232001f49Smrg   };
80332001f49Smrg   static const GLfloat vertices[4][2] = {
80432001f49Smrg      { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
80532001f49Smrg   };
80632001f49Smrg   static const GLfloat xforms[6][4] = {
80732001f49Smrg      {   0, 0, 1, 0 },
80832001f49Smrg      {  90, 0, 1, 0 },
80932001f49Smrg      { 180, 0, 1, 0 },
81032001f49Smrg      { 270, 0, 1, 0 },
81132001f49Smrg      {  90, 1, 0, 0 },
81232001f49Smrg      { -90, 1, 0, 0 }
81332001f49Smrg   };
81432001f49Smrg   static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
81532001f49Smrg   GLint i, j;
81632001f49Smrg
81732001f49Smrg   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
81832001f49Smrg   glEnable(GL_TEXTURE_2D);
81932001f49Smrg
82032001f49Smrg   glPushMatrix();
82132001f49Smrg   glRotatef(ViewRotX, 1.0, 0.0, 0.0);
82232001f49Smrg   glRotatef(15, 1, 0, 0);
82332001f49Smrg   glRotatef(CubeRot, 0, 1, 0);
82432001f49Smrg   glScalef(4, 4, 4);
82532001f49Smrg
82632001f49Smrg   for (i = 0; i < 6; i++) {
82732001f49Smrg      glPushMatrix();
82832001f49Smrg      glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
82932001f49Smrg      glTranslatef(0, 0, 1.1);
83032001f49Smrg      glBegin(GL_POLYGON);
83132001f49Smrg      glNormal3f(0, 0, 1);
83232001f49Smrg      for (j = 0; j < 4; j++) {
83332001f49Smrg	 glTexCoord2fv(texcoords[j]);
83432001f49Smrg	 glVertex2fv(vertices[j]);
83532001f49Smrg      }
83632001f49Smrg      glEnd();
83732001f49Smrg      glPopMatrix();
83832001f49Smrg   }
83932001f49Smrg   glPopMatrix();
84032001f49Smrg
84132001f49Smrg   glDisable(GL_TEXTURE_2D);
84232001f49Smrg}
84332001f49Smrg
84432001f49Smrg
84532001f49Smrgstatic void
84632001f49Smrgdraw(void)
84732001f49Smrg{
84832001f49Smrg   float ar;
84932001f49Smrg   static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
85032001f49Smrg
85132001f49Smrg   drawfire();
85232001f49Smrg
85332001f49Smrg   glLightfv(GL_LIGHT0, GL_POSITION, pos);
85432001f49Smrg   glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,
85532001f49Smrg		 GL_SEPARATE_SPECULAR_COLOR);
85632001f49Smrg
85732001f49Smrg   glEnable(GL_LIGHTING);
85832001f49Smrg   glEnable(GL_LIGHT0);
85932001f49Smrg   glEnable(GL_DEPTH_TEST);
86032001f49Smrg   glEnable(GL_NORMALIZE);
86132001f49Smrg   glDisable(GL_BLEND);
86232001f49Smrg   glDisable(GL_FOG);
86332001f49Smrg
86432001f49Smrg   glMatrixMode(GL_MODELVIEW);
86532001f49Smrg   glLoadIdentity();
86632001f49Smrg   glTranslatef(0.0, 0.0, -40.0);
86732001f49Smrg
86832001f49Smrg   glClear(GL_DEPTH_BUFFER_BIT);
86932001f49Smrg
87032001f49Smrg   /* draw textured cube */
87132001f49Smrg
87232001f49Smrg   glViewport(0, 0, WinWidth, WinHeight);
87332001f49Smrg   glClearColor(0.5, 0.5, 0.8, 0.0);
87432001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
87532001f49Smrg
87632001f49Smrg   ar = (float) (WinWidth) / WinHeight;
87732001f49Smrg   glMatrixMode(GL_PROJECTION);
87832001f49Smrg   glLoadIdentity();
87932001f49Smrg   glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
88032001f49Smrg   glMatrixMode(GL_MODELVIEW);
88132001f49Smrg   glBindTexture(GL_TEXTURE_2D, TexObj);
88232001f49Smrg
88332001f49Smrg   DrawCube();
88432001f49Smrg
88532001f49Smrg   /* finish up */
88632001f49Smrg   glutSwapBuffers();
88732001f49Smrg}
88832001f49Smrg
88932001f49Smrg
89032001f49Smrgstatic void
89132001f49Smrgidle(void)
89232001f49Smrg{
89332001f49Smrg   static double t0 = -1.;
89432001f49Smrg   double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
89532001f49Smrg   if (t0 < 0.0)
89632001f49Smrg      t0 = t;
89732001f49Smrg   dt = t - t0;
89832001f49Smrg   t0 = t;
89932001f49Smrg
90032001f49Smrg   CubeRot = fmod(CubeRot + 15.0 * dt, 360.0);  /* 15 deg/sec */
90132001f49Smrg
90232001f49Smrg   glutPostRedisplay();
90332001f49Smrg}
90432001f49Smrg
90532001f49Smrg
90632001f49Smrg/* change view angle */
90732001f49Smrgstatic void
90832001f49Smrgspecial(int k, int x, int y)
90932001f49Smrg{
91032001f49Smrg   (void) x;
91132001f49Smrg   (void) y;
91232001f49Smrg   switch (k) {
91332001f49Smrg   case GLUT_KEY_UP:
91432001f49Smrg      ViewRotX += 5.0;
91532001f49Smrg      break;
91632001f49Smrg   case GLUT_KEY_DOWN:
91732001f49Smrg      ViewRotX -= 5.0;
91832001f49Smrg      break;
91932001f49Smrg   case GLUT_KEY_LEFT:
92032001f49Smrg      ViewRotY += 5.0;
92132001f49Smrg      break;
92232001f49Smrg   case GLUT_KEY_RIGHT:
92332001f49Smrg      ViewRotY -= 5.0;
92432001f49Smrg      break;
92532001f49Smrg   default:
92632001f49Smrg      return;
92732001f49Smrg   }
92832001f49Smrg   glutPostRedisplay();
92932001f49Smrg}
93032001f49Smrg
93132001f49Smrg
93232001f49Smrg/* new window size or exposure */
93332001f49Smrgstatic void
93432001f49Smrgreshape(int width, int height)
93532001f49Smrg{
93632001f49Smrg   WinWidth = width;
93732001f49Smrg   WinHeight = height;
93832001f49Smrg}
93932001f49Smrg
94032001f49Smrg
94132001f49Smrgstatic void
94232001f49Smrginit_fbotexture(void)
94332001f49Smrg{
94432001f49Smrg   static const GLenum depthFormats[] = {
94532001f49Smrg      GL_DEPTH_COMPONENT,
94632001f49Smrg      GL_DEPTH_COMPONENT16,
94732001f49Smrg      GL_DEPTH_COMPONENT32
94832001f49Smrg   };
94932001f49Smrg   static int numDepthFormats = sizeof(depthFormats) / sizeof(depthFormats[0]);
95032001f49Smrg   GLint i;
95132001f49Smrg   GLenum stat;
95232001f49Smrg
95332001f49Smrg   /* gen framebuffer id, delete it, do some assertions, just for testing */
95432001f49Smrg   glGenFramebuffersEXT(1, &MyFB);
95532001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
95632001f49Smrg   glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
95732001f49Smrg
95832001f49Smrg   /* Make texture object/image */
95932001f49Smrg   glGenTextures(1, &TexObj);
96032001f49Smrg   glBindTexture(GL_TEXTURE_2D, TexObj);
96132001f49Smrg   /* make one image level. */
96232001f49Smrg   glTexImage2D(GL_TEXTURE_2D, 0, TEXINTFORMAT, TexWidth, TexHeight, 0,
96332001f49Smrg		texFormats[texType], texTypes[texType], NULL);
96432001f49Smrg
96532001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
96632001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
96732001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
96832001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
96932001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
97032001f49Smrg
97132001f49Smrg   CheckError(__LINE__);
97232001f49Smrg
97332001f49Smrg   /* Render color to texture */
97432001f49Smrg   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
97532001f49Smrg			     GL_TEXTURE_2D, TexObj, 0);
97632001f49Smrg   CheckError(__LINE__);
97732001f49Smrg
97832001f49Smrg
97932001f49Smrg   /* make depth renderbuffer */
98032001f49Smrg   glGenRenderbuffersEXT(1, &DepthRB);
98132001f49Smrg   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
98232001f49Smrg   /* we may have to try several formats */
98332001f49Smrg   for (i = 0; i < numDepthFormats; i++) {
98432001f49Smrg      glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthFormats[i],
98532001f49Smrg                               TexWidth, TexHeight);
98632001f49Smrg      CheckError(__LINE__);
98732001f49Smrg
98832001f49Smrg      glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
98932001f49Smrg                                   GL_RENDERBUFFER_EXT, DepthRB);
99032001f49Smrg      CheckError(__LINE__);
99132001f49Smrg      stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
99232001f49Smrg      if (stat == GL_FRAMEBUFFER_COMPLETE_EXT) {
99332001f49Smrg         break;
99432001f49Smrg      }
99532001f49Smrg   }
99632001f49Smrg
99732001f49Smrg   if (stat != GL_FRAMEBUFFER_COMPLETE_EXT) {
99832001f49Smrg      fprintf(stderr, "Error: unable to get usable FBO combination!\n");
99932001f49Smrg      exit(1);
100032001f49Smrg   }
100132001f49Smrg
100232001f49Smrg   glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
100332001f49Smrg                                   GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
100432001f49Smrg   CheckError(__LINE__);
100532001f49Smrg   printf("Depth renderbuffer size = %d bits\n", i);
100632001f49Smrg
100732001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
100832001f49Smrg
100932001f49Smrg   /*
101032001f49Smrg    * Check for completeness.
101132001f49Smrg    */
101232001f49Smrg
101332001f49Smrg}
101432001f49Smrg
101532001f49Smrg
101632001f49Smrgstatic void
101732001f49Smrginit(int argc, char *argv[])
101832001f49Smrg{
101932001f49Smrg   GLint i;
102032001f49Smrg
102132001f49Smrg   if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
102232001f49Smrg      fprintf(stderr, "Sorry, GL_EXT_framebuffer_object is required!\n");
102332001f49Smrg      exit(1);
102432001f49Smrg   }
102532001f49Smrg
102632001f49Smrg   TexWidth = 512;
102732001f49Smrg   TexHeight = 512;
102832001f49Smrg
102932001f49Smrg   init_fbotexture();
103032001f49Smrg   init_fire(argc, argv);
103132001f49Smrg
103232001f49Smrg
103332001f49Smrg   for ( i=1; i<argc; i++ ) {
103432001f49Smrg      if (strcmp(argv[i], "-info")==0) {
103532001f49Smrg	 printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
103632001f49Smrg	 printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
103732001f49Smrg	 printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
103832001f49Smrg	 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
103932001f49Smrg      }
104032001f49Smrg   }
104132001f49Smrg}
104232001f49Smrg
104332001f49Smrg
104432001f49Smrgstatic void
104532001f49Smrgvisible(int vis)
104632001f49Smrg{
104732001f49Smrg   if (vis == GLUT_VISIBLE)
104832001f49Smrg      glutIdleFunc(Anim ? idle : NULL);
104932001f49Smrg   else
105032001f49Smrg      glutIdleFunc(NULL);
105132001f49Smrg}
105232001f49Smrg
105332001f49Smrg
105432001f49Smrgint
105532001f49Smrgmain(int argc, char *argv[])
105632001f49Smrg{
105732001f49Smrg   glutInitWindowSize(WinWidth, WinHeight);
105832001f49Smrg   glutInit(&argc, argv);
105932001f49Smrg
106032001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
106132001f49Smrg
106232001f49Smrg   Win = glutCreateWindow("fbo_firecube");
106332001f49Smrg   glewInit();
106432001f49Smrg   init(argc, argv);
106532001f49Smrg
106632001f49Smrg   glutDisplayFunc(draw);
106732001f49Smrg   glutReshapeFunc(reshape);
106832001f49Smrg   glutKeyboardFunc(key);
106932001f49Smrg   glutSpecialFunc(special);
107032001f49Smrg   glutVisibilityFunc(visible);
107132001f49Smrg
107232001f49Smrg   glutMainLoop();
107332001f49Smrg   return 0;             /* ANSI C requires main to return int. */
107432001f49Smrg}
1075