2 * Draw the "fire" test program on the six faces of a cube using
3 * fbo render-to-texture.
5 * Much of the code comes from David Bucciarelli's "fire"
6 * test program. The rest basically from Brian Paul's "gearbox" and
9 * By pressing the 'q' key, you can make the driver choose different
10 * internal texture RGBA formats by giving it different "format" and "type"
11 * arguments to the glTexImage2D function that creates the texture
12 * image being rendered to. If the driver doesn't support a texture image
13 * format as a render target, it will usually fall back to software when
14 * drawing the "fire" image, and frame-rate should drop considerably.
17 * The rendering speed of this program is usually dictated by fill rate
18 * and the fact that software fallbacks for glBitMap makes the driver
19 * operate synchronously. Low-end UMA hardware will probably see around
20 * 35 fps with the help screen disabled and 32bpp window- and user
21 * frame-buffers (2008).
23 * This program is released under GPL, following the "fire" licensing.
26 * David Bucciarelli ("fire")
27 * Brian Paul ("gearbox", "fbotexture")
28 * Thomas Hellstrom (Putting it together)
42 * Format of texture we render to.
45 #define TEXINTFORMAT GL_RGBA
47 static GLuint texTypes
[] =
49 GL_UNSIGNED_INT_8_8_8_8_REV
,
50 GL_UNSIGNED_SHORT_1_5_5_5_REV
,
51 GL_UNSIGNED_SHORT_4_4_4_4_REV
,
52 GL_UNSIGNED_INT_8_8_8_8
,
53 GL_UNSIGNED_SHORT_5_5_5_1
,
54 GL_UNSIGNED_SHORT_4_4_4_4
,
55 GL_UNSIGNED_INT_8_8_8_8_REV
,
56 GL_UNSIGNED_SHORT_1_5_5_5_REV
,
57 GL_UNSIGNED_SHORT_4_4_4_4_REV
,
58 GL_UNSIGNED_INT_8_8_8_8
,
59 GL_UNSIGNED_SHORT_5_5_5_1
,
60 GL_UNSIGNED_SHORT_4_4_4_4
,
61 GL_UNSIGNED_SHORT_5_6_5
,
62 GL_UNSIGNED_SHORT_5_6_5_REV
,
63 GL_UNSIGNED_SHORT_5_6_5
,
64 GL_UNSIGNED_SHORT_5_6_5_REV
};
66 static GLuint texFormats
[] =
85 static const char *texNames
[] =
86 {"GL_RGBA GL_UNSIGNED_BYTE",
87 "GL_RGBA GL_UNSIGNED_INT_8_8_8_8_REV",
88 "GL_RGBA GL_UNSIGNED_SHORT_1_5_5_5_REV",
89 "GL_RGBA GL_UNSIGNED_SHORT_4_4_4_4_REV",
90 "GL_RGBA GL_UNSIGNED_INT_8_8_8_8",
91 "GL_RGBA GL_UNSIGNED_INT_5_5_5_1",
92 "GL_RGBA GL_UNSIGNED_INT_4_4_4_4",
93 "GL_BGRA GL_UNSIGNED_INT_8_8_8_8_REV",
94 "GL_BGRA GL_UNSIGNED_SHORT_1_5_5_5_REV",
95 "GL_BGRA GL_UNSIGNED_SHORT_4_4_4_4_REV",
96 "GL_BGRA GL_UNSIGNED_INT_8_8_8_8",
97 "GL_BGRA GL_UNSIGNED_INT_5_5_5_1",
98 "GL_BGRA GL_UNSIGNED_INT_4_4_4_4",
99 "GL_RGB GL_UNSIGNED_INT_5_6_5",
100 "GL_RGB GL_UNSIGNED_INT_5_6_5_REV",
101 "GL_BGR GL_UNSIGNED_INT_5_6_5",
102 "GL_BGR GL_UNSIGNED_INT_5_6_5_REV"};
108 #define M_PI 3.1415926535
111 #define vinit(a,i,j,k) { \
117 #define vinit4(a,i,j,k,w) { \
125 #define vadds(a,dt,b) { \
126 (a)[0]+=(dt)*(b)[0]; \
127 (a)[1]+=(dt)*(b)[1]; \
128 (a)[2]+=(dt)*(b)[2]; \
131 #define vequ(a,b) { \
137 #define vinter(a,dt,b,c) { \
138 (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0]; \
139 (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1]; \
140 (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2]; \
143 #define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
145 #define vclamp(v) { \
146 (v)[0]=clamp((v)[0]); \
147 (v)[1]=clamp((v)[1]); \
148 (v)[2]=clamp((v)[2]); \
151 static GLint WinWidth
= 800, WinHeight
= 800;
152 static GLint TexWidth
, TexHeight
;
153 static GLuint TexObj
;
155 static GLuint DepthRB
;
156 static GLboolean WireFrame
= GL_FALSE
;
157 static GLboolean Anim
= GL_TRUE
;
158 static GLint texType
= 0;
161 static GLint Frames
= 0;
162 static GLint Win
= 0;
164 static GLfloat ViewRotX
= 20.0, ViewRotY
= 30.0, ViewRotZ
= 0.0;
165 static GLfloat CubeRot
= 0.0;
175 GLenum err
= glGetError();
177 printf("GL Error 0x%x at line %d\n", (int) err
, line
);
186 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
187 glDeleteFramebuffersEXT(1, &MyFB
);
188 glDeleteRenderbuffersEXT(1, &DepthRB
);
189 glDeleteTextures(1, &TexObj
);
190 glutDestroyWindow(Win
);
193 static GLint NiceFog
= 1;
215 static float treepos
[NUMTREE
][3];
217 static float black
[3] = { 0.0, 0.0, 0.0 };
218 static float blu
[3] = { 1.0, 0.2, 0.0 };
219 static float blu2
[3] = { 1.0, 1.0, 0.0 };
221 static float fogcolor
[4] = { 1.0, 1.0, 1.0, 1.0 };
223 static float q
[4][3] = {
230 static float qt
[4][2] = {
238 static float eject_r
, dt
, maxage
, eject_vy
, eject_vl
;
239 static short shadows
;
246 static GLuint groundid
;
247 static GLuint treeid
;
249 static float obs
[3] = { 2.0, 1.0, 0.0 };
251 static float v
= 0.0;
252 static float alpha
= -84.0;
253 static float beta
= 90.0;
258 return (((float) rand()) / RAND_MAX
);
268 a
= vrnd() * 3.14159265359 * 2.0;
270 vinit(v
, sin(a
) * eject_r
* vrnd(), 0.15, cos(a
) * eject_r
* vrnd());
271 vinit(p
->p
[0], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
272 v
[2] + vrnd() * ridtri
);
273 vinit(p
->p
[1], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
274 v
[2] + vrnd() * ridtri
);
275 vinit(p
->p
[2], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
276 v
[2] + vrnd() * ridtri
);
278 vinit(p
->v
, v
[0] * eject_vl
/ (eject_r
/ 2),
279 vrnd() * eject_vy
+ eject_vy
/ 2, v
[2] * eject_vl
/ (eject_r
/ 2));
283 vinit4(p
->c
[0], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
284 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
285 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
286 vinit4(p
->c
[1], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
287 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
288 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
289 vinit4(p
->c
[2], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
290 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
291 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
299 if (p
->p
[0][1] < 0.1) {
304 p
->v
[1] += AGRAV
* dt
;
306 vadds(p
->p
[0], dt
, p
->v
);
307 vadds(p
->p
[1], dt
, p
->v
);
308 vadds(p
->p
[2], dt
, p
->v
);
312 if ((p
->age
) > maxage
) {
319 vadds(p
->c
[0], fact
, blu2
);
321 p
->c
[0][3] = fact
* (maxage
- p
->age
);
323 vadds(p
->c
[1], fact
, blu2
);
325 p
->c
[1][3] = fact
* (maxage
- p
->age
);
327 vadds(p
->c
[2], fact
, blu2
);
329 p
->c
[2][3] = fact
* (maxage
- p
->age
);
334 drawtree(float x
, float y
, float z
)
337 glTexCoord2f(0.0, 0.0);
338 glVertex3f(x
- 1.5, y
+ 0.0, z
);
340 glTexCoord2f(1.0, 0.0);
341 glVertex3f(x
+ 1.5, y
+ 0.0, z
);
343 glTexCoord2f(1.0, 1.0);
344 glVertex3f(x
+ 1.5, y
+ 3.0, z
);
346 glTexCoord2f(0.0, 1.0);
347 glVertex3f(x
- 1.5, y
+ 3.0, z
);
350 glTexCoord2f(0.0, 0.0);
351 glVertex3f(x
, y
+ 0.0, z
- 1.5);
353 glTexCoord2f(1.0, 0.0);
354 glVertex3f(x
, y
+ 0.0, z
+ 1.5);
356 glTexCoord2f(1.0, 1.0);
357 glVertex3f(x
, y
+ 3.0, z
+ 1.5);
359 glTexCoord2f(0.0, 1.0);
360 glVertex3f(x
, y
+ 3.0, z
- 1.5);
369 dir
[0] = sin(alpha
* M_PI
/ 180.0);
370 dir
[2] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
371 dir
[1] = cos(beta
* M_PI
/ 180.0);
373 if (dir
[0] < 1.0e-5 && dir
[0] > -1.0e-5)
375 if (dir
[1] < 1.0e-5 && dir
[1] > -1.0e-5)
377 if (dir
[2] < 1.0e-5 && dir
[2] > -1.0e-5)
380 obs
[0] += v
* dir
[0];
381 obs
[1] += v
* dir
[1];
382 obs
[2] += v
* dir
[2];
386 printstring(void *font
, const char *string
)
390 len
= (int) strlen(string
);
391 for (i
= 0; i
< len
; i
++)
392 glutBitmapCharacter(font
, string
[i
]);
399 glColor4f(0.0, 0.0, 0.0, 0.5);
400 glRecti(40, 40, 600, 440);
402 glColor3f(1.0, 0.0, 0.0);
403 glRasterPos2i(300, 420);
404 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Help");
406 glRasterPos2i(60, 390);
407 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "h - Toggle Help");
409 glRasterPos2i(60, 360);
410 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "t - Increase particle size");
411 glRasterPos2i(60, 330);
412 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "T - Decrease particle size");
414 glRasterPos2i(60, 300);
415 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "r - Increase emission radius");
416 glRasterPos2i(60, 270);
417 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "R - Decrease emission radius");
419 glRasterPos2i(60, 240);
420 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "f - Toggle Fog");
421 glRasterPos2i(60, 210);
422 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "s - Toggle shadows");
423 glRasterPos2i(60, 180);
424 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "q - Toggle texture format & type");
425 glRasterPos2i(60, 150);
426 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "a - Increase velocity");
427 glRasterPos2i(60, 120);
428 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "z - Decrease velocity");
429 glRasterPos2i(60, 90);
430 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Arrow Keys - Rotate");
437 static char frbuf
[80] = "";
439 static double t0
= -1.;
440 double t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
446 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
448 glDisable(GL_LIGHTING
);
450 glShadeModel(GL_FLAT
);
453 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
456 glFogi(GL_FOG_MODE
, GL_EXP
);
457 glFogfv(GL_FOG_COLOR
, fogcolor
);
458 glFogf(GL_FOG_DENSITY
, 0.1);
461 glViewport(0, 0, (GLint
) TexWidth
, (GLint
) TexHeight
);
462 glMatrixMode(GL_PROJECTION
);
464 gluPerspective(70.0, TexWidth
/ (float) TexHeight
, 0.1, 30.0);
466 glMatrixMode(GL_MODELVIEW
);
470 glHint(GL_FOG_HINT
, GL_NICEST
);
472 glHint(GL_FOG_HINT
, GL_DONT_CARE
);
474 glEnable(GL_DEPTH_TEST
);
481 glDepthMask(GL_TRUE
);
482 glClearColor(1.0, 1.0, 1.0, 1.0);
483 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
488 gluLookAt(obs
[0], obs
[1], obs
[2],
489 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
492 glColor4f(1.0, 1.0, 1.0, 1.0);
494 glEnable(GL_TEXTURE_2D
);
496 glBindTexture(GL_TEXTURE_2D
, groundid
);
498 glTexCoord2fv(qt
[0]);
500 glTexCoord2fv(qt
[1]);
502 glTexCoord2fv(qt
[2]);
504 glTexCoord2fv(qt
[3]);
508 glEnable(GL_ALPHA_TEST
);
509 glAlphaFunc(GL_GEQUAL
, 0.9);
511 glBindTexture(GL_TEXTURE_2D
, treeid
);
512 for (j
= 0; j
< NUMTREE
; j
++)
513 drawtree(treepos
[j
][0], treepos
[j
][1], treepos
[j
][2]);
515 glDisable(GL_TEXTURE_2D
);
516 glDepthMask(GL_FALSE
);
517 glDisable(GL_ALPHA_TEST
);
520 glBegin(GL_TRIANGLES
);
521 for (j
= 0; j
< np
; j
++) {
522 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[0][3]);
523 glVertex3f(p
[j
].p
[0][0], 0.1, p
[j
].p
[0][2]);
525 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[1][3]);
526 glVertex3f(p
[j
].p
[1][0], 0.1, p
[j
].p
[1][2]);
528 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[2][3]);
529 glVertex3f(p
[j
].p
[2][0], 0.1, p
[j
].p
[2][2]);
534 glBegin(GL_TRIANGLES
);
535 for (j
= 0; j
< np
; j
++) {
536 glColor4fv(p
[j
].c
[0]);
537 glVertex3fv(p
[j
].p
[0]);
539 glColor4fv(p
[j
].c
[1]);
540 glVertex3fv(p
[j
].p
[1]);
542 glColor4fv(p
[j
].c
[2]);
543 glVertex3fv(p
[j
].p
[2]);
550 glDisable(GL_TEXTURE_2D
);
551 glDisable(GL_ALPHA_TEST
);
552 glDisable(GL_DEPTH_TEST
);
555 glMatrixMode(GL_PROJECTION
);
557 glOrtho(-0.5, 639.5, -0.5, 479.5
559 glMatrixMode(GL_MODELVIEW
);
562 glColor3f(1.0, 0.0, 0.0);
563 glRasterPos2i(10, 10);
564 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
565 glColor3f(0.0, 0.0, 1.0);
566 glRasterPos2i(10, 450);
567 printstring(GLUT_BITMAP_HELVETICA_18
, texNames
[texType
]);
568 glColor3f(1.0, 0.0, 0.0);
569 glRasterPos2i(10, 470);
570 printstring(GLUT_BITMAP_HELVETICA_10
,
571 "Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
577 glDepthMask(GL_TRUE
);
578 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
582 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
583 if (t
- T0
>= 2000) {
584 GLfloat seconds
= (t
- T0
) / 1000.0;
585 GLfloat fps
= Frames
/ seconds
;
586 sprintf(frbuf
, "Frame rate: %f", fps
);
597 glBindTexture(GL_TEXTURE_2D
, TexObj
);
598 glTexImage2D(GL_TEXTURE_2D
, 0, TEXINTFORMAT
, TexWidth
, TexHeight
, 0,
599 texFormats
[texType
], texTypes
[texType
], NULL
);
600 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
601 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
,
602 GL_TEXTURE_2D
, TexObj
, 0);
603 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
607 key(unsigned char key
, int x
, int y
)
616 glutIdleFunc(Anim
? idle
: NULL
);
652 WireFrame
= !WireFrame
;
661 printf("NiceFog %d\n", NiceFog
);
671 GLubyte tex
[128][128][4];
673 glGenTextures(1, &groundid
);
674 glBindTexture(GL_TEXTURE_2D
, groundid
);
676 glPixelStorei(GL_UNPACK_ALIGNMENT
, 4);
677 if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB
)) {
678 fprintf(stderr
, "Error reading a texture.\n");
682 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
683 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
685 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
686 GL_LINEAR_MIPMAP_LINEAR
);
687 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
689 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
691 glGenTextures(1, &treeid
);
692 glBindTexture(GL_TEXTURE_2D
, treeid
);
699 GLubyte
*image
= LoadRGBImage("../images/tree3.rgb", &w
, &h
, &format
);
702 fprintf(stderr
, "Error reading a texture.\n");
706 for (y
= 0; y
< 128; y
++)
707 for (x
= 0; x
< 128; x
++) {
708 tex
[x
][y
][0] = image
[(y
+ x
* 128) * 3];
709 tex
[x
][y
][1] = image
[(y
+ x
* 128) * 3 + 1];
710 tex
[x
][y
][2] = image
[(y
+ x
* 128) * 3 + 2];
711 if ((tex
[x
][y
][0] == tex
[x
][y
][1]) &&
712 (tex
[x
][y
][1] == tex
[x
][y
][2]) && (tex
[x
][y
][2] == 255))
718 if ((gluerr
= gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, 128, 128, GL_RGBA
,
719 GL_UNSIGNED_BYTE
, (GLvoid
*) (tex
)))) {
720 fprintf(stderr
, "GLULib%s\n", (char *) gluErrorString(gluerr
));
725 if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA
)) {
726 fprintf(stderr
, "Error reading a texture.\n");
731 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
732 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
734 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
735 GL_LINEAR_MIPMAP_LINEAR
);
736 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
738 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
747 for (i
= 0; i
< NUMTREE
; i
++)
749 treepos
[i
][0] = vrnd() * TREEOUTR
* 2.0 - TREEOUTR
;
751 treepos
[i
][2] = vrnd() * TREEOUTR
* 2.0 - TREEOUTR
;
753 sqrt(treepos
[i
][0] * treepos
[i
][0] +
754 treepos
[i
][2] * treepos
[i
][2]);
755 } while ((dist
< TREEINR
) || (dist
> TREEOUTR
));
759 init_fire(int ac
, char *av
[])
779 p
= (part
*) malloc(sizeof(part
) * np
);
781 for (i
= 0; i
< np
; i
++)
797 static const GLfloat texcoords
[4][2] = {
798 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
800 static const GLfloat vertices
[4][2] = {
801 { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
803 static const GLfloat xforms
[6][4] = {
811 static const GLfloat mat
[4] = { 1.0, 1.0, 0.5, 1.0 };
814 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, mat
);
815 glEnable(GL_TEXTURE_2D
);
818 glRotatef(ViewRotX
, 1.0, 0.0, 0.0);
819 glRotatef(15, 1, 0, 0);
820 glRotatef(CubeRot
, 0, 1, 0);
823 for (i
= 0; i
< 6; i
++) {
825 glRotatef(xforms
[i
][0], xforms
[i
][1], xforms
[i
][2], xforms
[i
][3]);
826 glTranslatef(0, 0, 1.1);
829 for (j
= 0; j
< 4; j
++) {
830 glTexCoord2fv(texcoords
[j
]);
831 glVertex2fv(vertices
[j
]);
838 glDisable(GL_TEXTURE_2D
);
846 static GLfloat pos
[4] = {5.0, 5.0, 10.0, 0.0};
850 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
851 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL
,
852 GL_SEPARATE_SPECULAR_COLOR
);
854 glEnable(GL_LIGHTING
);
856 glEnable(GL_DEPTH_TEST
);
857 glEnable(GL_NORMALIZE
);
861 glMatrixMode(GL_MODELVIEW
);
863 glTranslatef(0.0, 0.0, -40.0);
865 glClear(GL_DEPTH_BUFFER_BIT
);
867 /* draw textured cube */
869 glViewport(0, 0, WinWidth
, WinHeight
);
870 glClearColor(0.5, 0.5, 0.8, 0.0);
871 glClear(GL_COLOR_BUFFER_BIT
);
873 ar
= (float) (WinWidth
) / WinHeight
;
874 glMatrixMode(GL_PROJECTION
);
876 glFrustum(-ar
, ar
, -1.0, 1.0, 5.0, 60.0);
877 glMatrixMode(GL_MODELVIEW
);
878 glBindTexture(GL_TEXTURE_2D
, TexObj
);
890 static double t0
= -1.;
891 double dt
, t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
897 CubeRot
= fmod(CubeRot
+ 15.0 * dt
, 360.0); /* 15 deg/sec */
903 /* change view angle */
905 special(int k
, int x
, int y
)
929 /* new window size or exposure */
931 reshape(int width
, int height
)
941 static const GLenum depthFormats
[] = {
943 GL_DEPTH_COMPONENT16
,
946 static int numDepthFormats
= sizeof(depthFormats
) / sizeof(depthFormats
[0]);
950 /* gen framebuffer id, delete it, do some assertions, just for testing */
951 glGenFramebuffersEXT(1, &MyFB
);
952 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
953 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &i
);
955 /* Make texture object/image */
956 glGenTextures(1, &TexObj
);
957 glBindTexture(GL_TEXTURE_2D
, TexObj
);
958 /* make one image level. */
959 glTexImage2D(GL_TEXTURE_2D
, 0, TEXINTFORMAT
, TexWidth
, TexHeight
, 0,
960 texFormats
[texType
], texTypes
[texType
], NULL
);
962 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
963 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
964 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
965 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_BASE_LEVEL
, 0);
966 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAX_LEVEL
, 0);
968 CheckError(__LINE__
);
970 /* Render color to texture */
971 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
,
972 GL_TEXTURE_2D
, TexObj
, 0);
973 CheckError(__LINE__
);
976 /* make depth renderbuffer */
977 glGenRenderbuffersEXT(1, &DepthRB
);
978 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, DepthRB
);
979 /* we may have to try several formats */
980 for (i
= 0; i
< numDepthFormats
; i
++) {
981 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, depthFormats
[i
],
982 TexWidth
, TexHeight
);
983 CheckError(__LINE__
);
985 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
,
986 GL_RENDERBUFFER_EXT
, DepthRB
);
987 CheckError(__LINE__
);
988 stat
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
989 if (stat
== GL_FRAMEBUFFER_COMPLETE_EXT
) {
994 if (stat
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
995 fprintf(stderr
, "Error: unable to get usable FBO combination!\n");
999 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT
,
1000 GL_RENDERBUFFER_DEPTH_SIZE_EXT
, &i
);
1001 CheckError(__LINE__
);
1002 printf("Depth renderbuffer size = %d bits\n", i
);
1004 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
1007 * Check for completeness.
1014 init(int argc
, char *argv
[])
1018 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
1019 fprintf(stderr
, "Sorry, GL_EXT_framebuffer_object is required!\n");
1027 init_fire(argc
, argv
);
1030 for ( i
=1; i
<argc
; i
++ ) {
1031 if (strcmp(argv
[i
], "-info")==0) {
1032 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
1033 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
1034 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
1035 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
1044 if (vis
== GLUT_VISIBLE
)
1045 glutIdleFunc(Anim
? idle
: NULL
);
1052 main(int argc
, char *argv
[])
1054 glutInitWindowSize(WinWidth
, WinHeight
);
1055 glutInit(&argc
, argv
);
1057 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
1059 Win
= glutCreateWindow("fbo_firecube");
1063 glutDisplayFunc(draw
);
1064 glutReshapeFunc(reshape
);
1065 glutKeyboardFunc(key
);
1066 glutSpecialFunc(special
);
1067 glutVisibilityFunc(visible
);
1070 return 0; /* ANSI C requires main to return int. */