Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fbo_firecube.c 23KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /*
  2. * Draw the "fire" test program on the six faces of a cube using
  3. * fbo render-to-texture.
  4. *
  5. * Much of the code comes from David Bucciarelli's "fire"
  6. * test program. The rest basically from Brian Paul's "gearbox" and
  7. * fbotexture programs.
  8. *
  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.
  15. *
  16. * Performance:
  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).
  22. *
  23. * This program is released under GPL, following the "fire" licensing.
  24. *
  25. * Authors:
  26. * David Bucciarelli ("fire")
  27. * Brian Paul ("gearbox", "fbotexture")
  28. * Thomas Hellstrom (Putting it together)
  29. *
  30. */
  31. #include <math.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <GL/glew.h>
  36. #include <GL/glut.h>
  37. #include "readtex.h"
  38. /*
  39. * Format of texture we render to.
  40. */
  41. #define TEXINTFORMAT GL_RGBA
  42. static GLuint texTypes[] =
  43. {GL_UNSIGNED_BYTE,
  44. GL_UNSIGNED_INT_8_8_8_8_REV,
  45. GL_UNSIGNED_SHORT_1_5_5_5_REV,
  46. GL_UNSIGNED_SHORT_4_4_4_4_REV,
  47. GL_UNSIGNED_INT_8_8_8_8,
  48. GL_UNSIGNED_SHORT_5_5_5_1,
  49. GL_UNSIGNED_SHORT_4_4_4_4,
  50. GL_UNSIGNED_INT_8_8_8_8_REV,
  51. GL_UNSIGNED_SHORT_1_5_5_5_REV,
  52. GL_UNSIGNED_SHORT_4_4_4_4_REV,
  53. GL_UNSIGNED_INT_8_8_8_8,
  54. GL_UNSIGNED_SHORT_5_5_5_1,
  55. GL_UNSIGNED_SHORT_4_4_4_4,
  56. GL_UNSIGNED_SHORT_5_6_5,
  57. GL_UNSIGNED_SHORT_5_6_5_REV,
  58. GL_UNSIGNED_SHORT_5_6_5,
  59. GL_UNSIGNED_SHORT_5_6_5_REV};
  60. static GLuint texFormats[] =
  61. {GL_RGBA,
  62. GL_RGBA,
  63. GL_RGBA,
  64. GL_RGBA,
  65. GL_RGBA,
  66. GL_RGBA,
  67. GL_RGBA,
  68. GL_BGRA,
  69. GL_BGRA,
  70. GL_BGRA,
  71. GL_BGRA,
  72. GL_BGRA,
  73. GL_BGRA,
  74. GL_RGB,
  75. GL_RGB,
  76. GL_BGR,
  77. GL_BGR};
  78. static const char *texNames[] =
  79. {"GL_RGBA GL_UNSIGNED_BYTE",
  80. "GL_RGBA GL_UNSIGNED_INT_8_8_8_8_REV",
  81. "GL_RGBA GL_UNSIGNED_SHORT_1_5_5_5_REV",
  82. "GL_RGBA GL_UNSIGNED_SHORT_4_4_4_4_REV",
  83. "GL_RGBA GL_UNSIGNED_INT_8_8_8_8",
  84. "GL_RGBA GL_UNSIGNED_INT_5_5_5_1",
  85. "GL_RGBA GL_UNSIGNED_INT_4_4_4_4",
  86. "GL_BGRA GL_UNSIGNED_INT_8_8_8_8_REV",
  87. "GL_BGRA GL_UNSIGNED_SHORT_1_5_5_5_REV",
  88. "GL_BGRA GL_UNSIGNED_SHORT_4_4_4_4_REV",
  89. "GL_BGRA GL_UNSIGNED_INT_8_8_8_8",
  90. "GL_BGRA GL_UNSIGNED_INT_5_5_5_1",
  91. "GL_BGRA GL_UNSIGNED_INT_4_4_4_4",
  92. "GL_RGB GL_UNSIGNED_INT_5_6_5",
  93. "GL_RGB GL_UNSIGNED_INT_5_6_5_REV",
  94. "GL_BGR GL_UNSIGNED_INT_5_6_5",
  95. "GL_BGR GL_UNSIGNED_INT_5_6_5_REV"};
  96. #ifndef M_PI
  97. #define M_PI 3.1415926535
  98. #endif
  99. #define vinit(a,i,j,k) { \
  100. (a)[0]=i; \
  101. (a)[1]=j; \
  102. (a)[2]=k; \
  103. }
  104. #define vinit4(a,i,j,k,w) { \
  105. (a)[0]=i; \
  106. (a)[1]=j; \
  107. (a)[2]=k; \
  108. (a)[3]=w; \
  109. }
  110. #define vadds(a,dt,b) { \
  111. (a)[0]+=(dt)*(b)[0]; \
  112. (a)[1]+=(dt)*(b)[1]; \
  113. (a)[2]+=(dt)*(b)[2]; \
  114. }
  115. #define vequ(a,b) { \
  116. (a)[0]=(b)[0]; \
  117. (a)[1]=(b)[1]; \
  118. (a)[2]=(b)[2]; \
  119. }
  120. #define vinter(a,dt,b,c) { \
  121. (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0]; \
  122. (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1]; \
  123. (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2]; \
  124. }
  125. #define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
  126. #define vclamp(v) { \
  127. (v)[0]=clamp((v)[0]); \
  128. (v)[1]=clamp((v)[1]); \
  129. (v)[2]=clamp((v)[2]); \
  130. }
  131. static GLint WinWidth = 800, WinHeight = 800;
  132. static GLint TexWidth, TexHeight;
  133. static GLuint TexObj;
  134. static GLuint MyFB;
  135. static GLuint DepthRB;
  136. static GLboolean WireFrame = GL_FALSE;
  137. static GLboolean Anim = GL_TRUE;
  138. static GLint texType = 0;
  139. static GLint T0 = 0;
  140. static GLint Frames = 0;
  141. static GLint Win = 0;
  142. static GLfloat ViewRotX = 20.0, ViewRotY = 30.0, ViewRotZ = 0.0;
  143. static GLfloat CubeRot = 0.0;
  144. static void
  145. idle(void);
  146. static void
  147. CheckError(int line)
  148. {
  149. GLenum err = glGetError();
  150. if (err) {
  151. printf("GL Error 0x%x at line %d\n", (int) err, line);
  152. exit(1);
  153. }
  154. }
  155. static void
  156. cleanup(void)
  157. {
  158. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  159. glDeleteFramebuffersEXT(1, &MyFB);
  160. glDeleteRenderbuffersEXT(1, &DepthRB);
  161. glDeleteTextures(1, &TexObj);
  162. glutDestroyWindow(Win);
  163. }
  164. static GLint NiceFog = 1;
  165. #define DIMP 20.0
  166. #define DIMTP 16.0
  167. #define RIDCOL 0.4
  168. #define NUMTREE 50
  169. #define TREEINR 2.5
  170. #define TREEOUTR 8.0
  171. #define AGRAV -9.8
  172. typedef struct
  173. {
  174. int age;
  175. float p[3][3];
  176. float v[3];
  177. float c[3][4];
  178. }
  179. part;
  180. static float treepos[NUMTREE][3];
  181. static float black[3] = { 0.0, 0.0, 0.0 };
  182. static float blu[3] = { 1.0, 0.2, 0.0 };
  183. static float blu2[3] = { 1.0, 1.0, 0.0 };
  184. static float fogcolor[4] = { 1.0, 1.0, 1.0, 1.0 };
  185. static float q[4][3] = {
  186. {-DIMP, 0.0, -DIMP},
  187. {DIMP, 0.0, -DIMP},
  188. {DIMP, 0.0, DIMP},
  189. {-DIMP, 0.0, DIMP}
  190. };
  191. static float qt[4][2] = {
  192. {-DIMTP, -DIMTP},
  193. {DIMTP, -DIMTP},
  194. {DIMTP, DIMTP},
  195. {-DIMTP, DIMTP}
  196. };
  197. static int np;
  198. static float eject_r, dt, maxage, eject_vy, eject_vl;
  199. static short shadows;
  200. static float ridtri;
  201. static int fog = 0;
  202. static int help = 1;
  203. static part *p;
  204. static GLuint groundid;
  205. static GLuint treeid;
  206. static float obs[3] = { 2.0, 1.0, 0.0 };
  207. static float dir[3];
  208. static float v = 0.0;
  209. static float alpha = -84.0;
  210. static float beta = 90.0;
  211. static float
  212. vrnd(void)
  213. {
  214. return (((float) rand()) / RAND_MAX);
  215. }
  216. static void
  217. setnewpart(part * p)
  218. {
  219. float a, v[3], *c;
  220. p->age = 0;
  221. a = vrnd() * 3.14159265359 * 2.0;
  222. vinit(v, sin(a) * eject_r * vrnd(), 0.15, cos(a) * eject_r * vrnd());
  223. vinit(p->p[0], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
  224. v[2] + vrnd() * ridtri);
  225. vinit(p->p[1], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
  226. v[2] + vrnd() * ridtri);
  227. vinit(p->p[2], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
  228. v[2] + vrnd() * ridtri);
  229. vinit(p->v, v[0] * eject_vl / (eject_r / 2),
  230. vrnd() * eject_vy + eject_vy / 2, v[2] * eject_vl / (eject_r / 2));
  231. c = blu;
  232. vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
  233. c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
  234. c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
  235. vinit4(p->c[1], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
  236. c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
  237. c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
  238. vinit4(p->c[2], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
  239. c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
  240. c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
  241. }
  242. static void
  243. setpart(part * p)
  244. {
  245. float fact;
  246. if (p->p[0][1] < 0.1) {
  247. setnewpart(p);
  248. return;
  249. }
  250. p->v[1] += AGRAV * dt;
  251. vadds(p->p[0], dt, p->v);
  252. vadds(p->p[1], dt, p->v);
  253. vadds(p->p[2], dt, p->v);
  254. p->age++;
  255. if ((p->age) > maxage) {
  256. vequ(p->c[0], blu2);
  257. vequ(p->c[1], blu2);
  258. vequ(p->c[2], blu2);
  259. }
  260. else {
  261. fact = 1.0 / maxage;
  262. vadds(p->c[0], fact, blu2);
  263. vclamp(p->c[0]);
  264. p->c[0][3] = fact * (maxage - p->age);
  265. vadds(p->c[1], fact, blu2);
  266. vclamp(p->c[1]);
  267. p->c[1][3] = fact * (maxage - p->age);
  268. vadds(p->c[2], fact, blu2);
  269. vclamp(p->c[2]);
  270. p->c[2][3] = fact * (maxage - p->age);
  271. }
  272. }
  273. static void
  274. drawtree(float x, float y, float z)
  275. {
  276. glBegin(GL_QUADS);
  277. glTexCoord2f(0.0, 0.0);
  278. glVertex3f(x - 1.5, y + 0.0, z);
  279. glTexCoord2f(1.0, 0.0);
  280. glVertex3f(x + 1.5, y + 0.0, z);
  281. glTexCoord2f(1.0, 1.0);
  282. glVertex3f(x + 1.5, y + 3.0, z);
  283. glTexCoord2f(0.0, 1.0);
  284. glVertex3f(x - 1.5, y + 3.0, z);
  285. glTexCoord2f(0.0, 0.0);
  286. glVertex3f(x, y + 0.0, z - 1.5);
  287. glTexCoord2f(1.0, 0.0);
  288. glVertex3f(x, y + 0.0, z + 1.5);
  289. glTexCoord2f(1.0, 1.0);
  290. glVertex3f(x, y + 3.0, z + 1.5);
  291. glTexCoord2f(0.0, 1.0);
  292. glVertex3f(x, y + 3.0, z - 1.5);
  293. glEnd();
  294. }
  295. static void
  296. calcposobs(void)
  297. {
  298. dir[0] = sin(alpha * M_PI / 180.0);
  299. dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
  300. dir[1] = cos(beta * M_PI / 180.0);
  301. if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
  302. dir[0] = 0;
  303. if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
  304. dir[1] = 0;
  305. if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
  306. dir[2] = 0;
  307. obs[0] += v * dir[0];
  308. obs[1] += v * dir[1];
  309. obs[2] += v * dir[2];
  310. }
  311. static void
  312. printstring(void *font, const char *string)
  313. {
  314. int len, i;
  315. len = (int) strlen(string);
  316. for (i = 0; i < len; i++)
  317. glutBitmapCharacter(font, string[i]);
  318. }
  319. static void
  320. printhelp(void)
  321. {
  322. glColor4f(0.0, 0.0, 0.0, 0.5);
  323. glRecti(40, 40, 600, 440);
  324. glColor3f(1.0, 0.0, 0.0);
  325. glRasterPos2i(300, 420);
  326. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
  327. glRasterPos2i(60, 390);
  328. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
  329. glRasterPos2i(60, 360);
  330. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Increase particle size");
  331. glRasterPos2i(60, 330);
  332. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "T - Decrease particle size");
  333. glRasterPos2i(60, 300);
  334. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "r - Increase emission radius");
  335. glRasterPos2i(60, 270);
  336. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "R - Decrease emission radius");
  337. glRasterPos2i(60, 240);
  338. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
  339. glRasterPos2i(60, 210);
  340. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "s - Toggle shadows");
  341. glRasterPos2i(60, 180);
  342. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "q - Toggle texture format & type");
  343. glRasterPos2i(60, 150);
  344. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
  345. glRasterPos2i(60, 120);
  346. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
  347. glRasterPos2i(60, 90);
  348. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
  349. }
  350. static void
  351. drawfire(void)
  352. {
  353. static char frbuf[80] = "";
  354. int j;
  355. static double t0 = -1.;
  356. double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  357. if (t0 < 0.0)
  358. t0 = t;
  359. dt = (t - t0) * 1.0;
  360. t0 = t;
  361. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
  362. glDisable(GL_LIGHTING);
  363. glShadeModel(GL_FLAT);
  364. glEnable(GL_BLEND);
  365. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  366. glEnable(GL_FOG);
  367. glFogi(GL_FOG_MODE, GL_EXP);
  368. glFogfv(GL_FOG_COLOR, fogcolor);
  369. glFogf(GL_FOG_DENSITY, 0.1);
  370. glViewport(0, 0, (GLint) TexWidth, (GLint) TexHeight);
  371. glMatrixMode(GL_PROJECTION);
  372. glLoadIdentity();
  373. gluPerspective(70.0, TexWidth/ (float) TexHeight, 0.1, 30.0);
  374. glMatrixMode(GL_MODELVIEW);
  375. glLoadIdentity();
  376. if (NiceFog)
  377. glHint(GL_FOG_HINT, GL_NICEST);
  378. else
  379. glHint(GL_FOG_HINT, GL_DONT_CARE);
  380. glEnable(GL_DEPTH_TEST);
  381. if (fog)
  382. glEnable(GL_FOG);
  383. else
  384. glDisable(GL_FOG);
  385. glDepthMask(GL_TRUE);
  386. glClearColor(1.0, 1.0, 1.0, 1.0);
  387. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  388. glPushMatrix();
  389. calcposobs();
  390. gluLookAt(obs[0], obs[1], obs[2],
  391. obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
  392. 0.0, 1.0, 0.0);
  393. glColor4f(1.0, 1.0, 1.0, 1.0);
  394. glEnable(GL_TEXTURE_2D);
  395. glBindTexture(GL_TEXTURE_2D, groundid);
  396. glBegin(GL_QUADS);
  397. glTexCoord2fv(qt[0]);
  398. glVertex3fv(q[0]);
  399. glTexCoord2fv(qt[1]);
  400. glVertex3fv(q[1]);
  401. glTexCoord2fv(qt[2]);
  402. glVertex3fv(q[2]);
  403. glTexCoord2fv(qt[3]);
  404. glVertex3fv(q[3]);
  405. glEnd();
  406. glEnable(GL_ALPHA_TEST);
  407. glAlphaFunc(GL_GEQUAL, 0.9);
  408. glBindTexture(GL_TEXTURE_2D, treeid);
  409. for (j = 0; j < NUMTREE; j++)
  410. drawtree(treepos[j][0], treepos[j][1], treepos[j][2]);
  411. glDisable(GL_TEXTURE_2D);
  412. glDepthMask(GL_FALSE);
  413. glDisable(GL_ALPHA_TEST);
  414. if (shadows) {
  415. glBegin(GL_TRIANGLES);
  416. for (j = 0; j < np; j++) {
  417. glColor4f(black[0], black[1], black[2], p[j].c[0][3]);
  418. glVertex3f(p[j].p[0][0], 0.1, p[j].p[0][2]);
  419. glColor4f(black[0], black[1], black[2], p[j].c[1][3]);
  420. glVertex3f(p[j].p[1][0], 0.1, p[j].p[1][2]);
  421. glColor4f(black[0], black[1], black[2], p[j].c[2][3]);
  422. glVertex3f(p[j].p[2][0], 0.1, p[j].p[2][2]);
  423. }
  424. glEnd();
  425. }
  426. glBegin(GL_TRIANGLES);
  427. for (j = 0; j < np; j++) {
  428. glColor4fv(p[j].c[0]);
  429. glVertex3fv(p[j].p[0]);
  430. glColor4fv(p[j].c[1]);
  431. glVertex3fv(p[j].p[1]);
  432. glColor4fv(p[j].c[2]);
  433. glVertex3fv(p[j].p[2]);
  434. setpart(&p[j]);
  435. }
  436. glEnd();
  437. glDisable(GL_TEXTURE_2D);
  438. glDisable(GL_ALPHA_TEST);
  439. glDisable(GL_DEPTH_TEST);
  440. glDisable(GL_FOG);
  441. glMatrixMode(GL_PROJECTION);
  442. glLoadIdentity();
  443. glOrtho(-0.5, 639.5, -0.5, 479.5
  444. , -1.0, 1.0);
  445. glMatrixMode(GL_MODELVIEW);
  446. glLoadIdentity();
  447. glColor3f(1.0, 0.0, 0.0);
  448. glRasterPos2i(10, 10);
  449. printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
  450. glColor3f(0.0, 0.0, 1.0);
  451. glRasterPos2i(10, 450);
  452. printstring(GLUT_BITMAP_HELVETICA_18, texNames[texType]);
  453. glColor3f(1.0, 0.0, 0.0);
  454. glRasterPos2i(10, 470);
  455. printstring(GLUT_BITMAP_HELVETICA_10,
  456. "Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
  457. if (help)
  458. printhelp();
  459. glPopMatrix();
  460. glDepthMask(GL_TRUE);
  461. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  462. Frames++;
  463. {
  464. GLint t = glutGet(GLUT_ELAPSED_TIME);
  465. if (t - T0 >= 2000) {
  466. GLfloat seconds = (t - T0) / 1000.0;
  467. GLfloat fps = Frames / seconds;
  468. sprintf(frbuf, "Frame rate: %f", fps);
  469. T0 = t;
  470. Frames = 0;
  471. }
  472. }
  473. }
  474. static void
  475. regen_texImage(void)
  476. {
  477. glBindTexture(GL_TEXTURE_2D, TexObj);
  478. glTexImage2D(GL_TEXTURE_2D, 0, TEXINTFORMAT, TexWidth, TexHeight, 0,
  479. texFormats[texType], texTypes[texType], NULL);
  480. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
  481. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
  482. GL_TEXTURE_2D, TexObj, 0);
  483. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  484. }
  485. static void
  486. key(unsigned char key, int x, int y)
  487. {
  488. switch (key) {
  489. case 27:
  490. cleanup();
  491. exit(0);
  492. break;
  493. case ' ':
  494. Anim = !Anim;
  495. glutIdleFunc(Anim ? idle : NULL);
  496. break;
  497. case 'a':
  498. v += 0.0005;
  499. break;
  500. case 'z':
  501. v -= 0.0005;
  502. break;
  503. case 'h':
  504. help = (!help);
  505. break;
  506. case 'f':
  507. fog = (!fog);
  508. break;
  509. case 's':
  510. shadows = !shadows;
  511. break;
  512. case 'R':
  513. eject_r -= 0.03;
  514. break;
  515. case 'r':
  516. eject_r += 0.03;
  517. break;
  518. case 't':
  519. ridtri += 0.005;
  520. break;
  521. case 'T':
  522. ridtri -= 0.005;
  523. break;
  524. case 'v':
  525. ViewRotZ += 5.0;
  526. break;
  527. case 'V':
  528. ViewRotZ -= 5.0;
  529. break;
  530. case 'w':
  531. WireFrame = !WireFrame;
  532. break;
  533. case 'q':
  534. if (++texType > 16)
  535. texType = 0;
  536. regen_texImage();
  537. break;
  538. case 'n':
  539. NiceFog = !NiceFog;
  540. printf("NiceFog %d\n", NiceFog);
  541. break;
  542. }
  543. glutPostRedisplay();
  544. }
  545. static void
  546. inittextures(void)
  547. {
  548. GLenum gluerr;
  549. GLubyte tex[128][128][4];
  550. glGenTextures(1, &groundid);
  551. glBindTexture(GL_TEXTURE_2D, groundid);
  552. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  553. if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB)) {
  554. fprintf(stderr, "Error reading a texture.\n");
  555. exit(-1);
  556. }
  557. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  558. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  559. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  560. GL_LINEAR_MIPMAP_LINEAR);
  561. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  562. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  563. glGenTextures(1, &treeid);
  564. glBindTexture(GL_TEXTURE_2D, treeid);
  565. if (1)
  566. {
  567. int w, h;
  568. GLenum format;
  569. int x, y;
  570. GLubyte *image = LoadRGBImage("../images/tree3.rgb", &w, &h, &format);
  571. if (!image) {
  572. fprintf(stderr, "Error reading a texture.\n");
  573. exit(-1);
  574. }
  575. for (y = 0; y < 128; y++)
  576. for (x = 0; x < 128; x++) {
  577. tex[x][y][0] = image[(y + x * 128) * 3];
  578. tex[x][y][1] = image[(y + x * 128) * 3 + 1];
  579. tex[x][y][2] = image[(y + x * 128) * 3 + 2];
  580. if ((tex[x][y][0] == tex[x][y][1]) &&
  581. (tex[x][y][1] == tex[x][y][2]) && (tex[x][y][2] == 255))
  582. tex[x][y][3] = 0;
  583. else
  584. tex[x][y][3] = 255;
  585. }
  586. if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA,
  587. GL_UNSIGNED_BYTE, (GLvoid *) (tex)))) {
  588. fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr));
  589. exit(-1);
  590. }
  591. }
  592. else {
  593. if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA)) {
  594. fprintf(stderr, "Error reading a texture.\n");
  595. exit(-1);
  596. }
  597. }
  598. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  599. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  600. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  601. GL_LINEAR_MIPMAP_LINEAR);
  602. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  603. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  604. }
  605. static void
  606. inittree(void)
  607. {
  608. int i;
  609. float dist;
  610. for (i = 0; i < NUMTREE; i++)
  611. do {
  612. treepos[i][0] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
  613. treepos[i][1] = 0.0;
  614. treepos[i][2] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
  615. dist =
  616. sqrt(treepos[i][0] * treepos[i][0] +
  617. treepos[i][2] * treepos[i][2]);
  618. } while ((dist < TREEINR) || (dist > TREEOUTR));
  619. }
  620. static int
  621. init_fire(int ac, char *av[])
  622. {
  623. int i;
  624. np = 800;
  625. eject_r = -0.65;
  626. dt = 0.015;
  627. eject_vy = 4;
  628. eject_vl = 1;
  629. shadows = 1;
  630. ridtri = 0.25;
  631. maxage = 1.0 / dt;
  632. if (ac == 2)
  633. np = atoi(av[1]);
  634. inittextures();
  635. p = (part *) malloc(sizeof(part) * np);
  636. for (i = 0; i < np; i++)
  637. setnewpart(&p[i]);
  638. inittree();
  639. return (0);
  640. }
  641. static void
  642. DrawCube(void)
  643. {
  644. static const GLfloat texcoords[4][2] = {
  645. { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
  646. };
  647. static const GLfloat vertices[4][2] = {
  648. { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
  649. };
  650. static const GLfloat xforms[6][4] = {
  651. { 0, 0, 1, 0 },
  652. { 90, 0, 1, 0 },
  653. { 180, 0, 1, 0 },
  654. { 270, 0, 1, 0 },
  655. { 90, 1, 0, 0 },
  656. { -90, 1, 0, 0 }
  657. };
  658. static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
  659. GLint i, j;
  660. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
  661. glEnable(GL_TEXTURE_2D);
  662. glPushMatrix();
  663. glRotatef(ViewRotX, 1.0, 0.0, 0.0);
  664. glRotatef(15, 1, 0, 0);
  665. glRotatef(CubeRot, 0, 1, 0);
  666. glScalef(4, 4, 4);
  667. for (i = 0; i < 6; i++) {
  668. glPushMatrix();
  669. glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
  670. glTranslatef(0, 0, 1.1);
  671. glBegin(GL_POLYGON);
  672. glNormal3f(0, 0, 1);
  673. for (j = 0; j < 4; j++) {
  674. glTexCoord2fv(texcoords[j]);
  675. glVertex2fv(vertices[j]);
  676. }
  677. glEnd();
  678. glPopMatrix();
  679. }
  680. glPopMatrix();
  681. glDisable(GL_TEXTURE_2D);
  682. }
  683. static void
  684. draw(void)
  685. {
  686. float ar;
  687. static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
  688. drawfire();
  689. glLightfv(GL_LIGHT0, GL_POSITION, pos);
  690. glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,
  691. GL_SEPARATE_SPECULAR_COLOR);
  692. glEnable(GL_LIGHTING);
  693. glEnable(GL_LIGHT0);
  694. glEnable(GL_DEPTH_TEST);
  695. glEnable(GL_NORMALIZE);
  696. glDisable(GL_BLEND);
  697. glDisable(GL_FOG);
  698. glMatrixMode(GL_MODELVIEW);
  699. glLoadIdentity();
  700. glTranslatef(0.0, 0.0, -40.0);
  701. glClear(GL_DEPTH_BUFFER_BIT);
  702. /* draw textured cube */
  703. glViewport(0, 0, WinWidth, WinHeight);
  704. glClearColor(0.5, 0.5, 0.8, 0.0);
  705. glClear(GL_COLOR_BUFFER_BIT);
  706. ar = (float) (WinWidth) / WinHeight;
  707. glMatrixMode(GL_PROJECTION);
  708. glLoadIdentity();
  709. glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
  710. glMatrixMode(GL_MODELVIEW);
  711. glBindTexture(GL_TEXTURE_2D, TexObj);
  712. DrawCube();
  713. /* finish up */
  714. glutSwapBuffers();
  715. }
  716. static void
  717. idle(void)
  718. {
  719. static double t0 = -1.;
  720. double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  721. if (t0 < 0.0)
  722. t0 = t;
  723. dt = t - t0;
  724. t0 = t;
  725. CubeRot = fmod(CubeRot + 15.0 * dt, 360.0); /* 15 deg/sec */
  726. glutPostRedisplay();
  727. }
  728. /* change view angle */
  729. static void
  730. special(int k, int x, int y)
  731. {
  732. (void) x;
  733. (void) y;
  734. switch (k) {
  735. case GLUT_KEY_UP:
  736. ViewRotX += 5.0;
  737. break;
  738. case GLUT_KEY_DOWN:
  739. ViewRotX -= 5.0;
  740. break;
  741. case GLUT_KEY_LEFT:
  742. ViewRotY += 5.0;
  743. break;
  744. case GLUT_KEY_RIGHT:
  745. ViewRotY -= 5.0;
  746. break;
  747. default:
  748. return;
  749. }
  750. glutPostRedisplay();
  751. }
  752. /* new window size or exposure */
  753. static void
  754. reshape(int width, int height)
  755. {
  756. WinWidth = width;
  757. WinHeight = height;
  758. }
  759. static void
  760. init_fbotexture()
  761. {
  762. GLint i;
  763. /* gen framebuffer id, delete it, do some assertions, just for testing */
  764. glGenFramebuffersEXT(1, &MyFB);
  765. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
  766. glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
  767. /* Make texture object/image */
  768. glGenTextures(1, &TexObj);
  769. glBindTexture(GL_TEXTURE_2D, TexObj);
  770. /* make one image level. */
  771. glTexImage2D(GL_TEXTURE_2D, 0, TEXINTFORMAT, TexWidth, TexHeight, 0,
  772. texFormats[texType], texTypes[texType], NULL);
  773. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  774. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  775. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  776. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
  777. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  778. CheckError(__LINE__);
  779. /* Render color to texture */
  780. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
  781. GL_TEXTURE_2D, TexObj, 0);
  782. CheckError(__LINE__);
  783. /* make depth renderbuffer */
  784. glGenRenderbuffersEXT(1, &DepthRB);
  785. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
  786. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
  787. TexWidth, TexHeight);
  788. CheckError(__LINE__);
  789. glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
  790. GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
  791. CheckError(__LINE__);
  792. printf("Depth renderbuffer size = %d bits\n", i);
  793. /* attach DepthRB to MyFB */
  794. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
  795. GL_RENDERBUFFER_EXT, DepthRB);
  796. CheckError(__LINE__);
  797. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  798. /*
  799. * Check for completeness.
  800. */
  801. }
  802. static void
  803. init(int argc, char *argv[])
  804. {
  805. GLint i;
  806. if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
  807. fprintf(stderr, "Sorry, GL_EXT_framebuffer_object is required!\n");
  808. exit(1);
  809. }
  810. TexWidth = 512;
  811. TexHeight = 512;
  812. init_fbotexture();
  813. init_fire(argc, argv);
  814. for ( i=1; i<argc; i++ ) {
  815. if (strcmp(argv[i], "-info")==0) {
  816. printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
  817. printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
  818. printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
  819. printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
  820. }
  821. }
  822. }
  823. static void
  824. visible(int vis)
  825. {
  826. if (vis == GLUT_VISIBLE)
  827. glutIdleFunc(Anim ? idle : NULL);
  828. else
  829. glutIdleFunc(NULL);
  830. }
  831. int
  832. main(int argc, char *argv[])
  833. {
  834. glutInit(&argc, argv);
  835. glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
  836. glutInitWindowSize(WinWidth, WinHeight);
  837. Win = glutCreateWindow("fbo_firecube");
  838. glewInit();
  839. init(argc, argv);
  840. glutDisplayFunc(draw);
  841. glutReshapeFunc(reshape);
  842. glutKeyboardFunc(key);
  843. glutSpecialFunc(special);
  844. glutVisibilityFunc(visible);
  845. glutMainLoop();
  846. return 0; /* ANSI C requires main to return int. */
  847. }