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.

gloss.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * Specular reflection demo. The specular highlight is modulated by
  3. * a sphere-mapped texture. The result is a high-gloss surface.
  4. * NOTE: you really need hardware acceleration for this.
  5. * Also note, this technique can't be implemented with multi-texture
  6. * and separate specular color interpolation because there's no way
  7. * to indicate that the second texture unit (the reflection map)
  8. * should modulate the specular color and not the base color.
  9. * A future multi-texture extension could fix that.
  10. *
  11. * Command line options:
  12. * -info print GL implementation information
  13. *
  14. *
  15. * Brian Paul October 22, 1999 This program is in the public domain.
  16. */
  17. #include <assert.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <math.h>
  21. #include <string.h>
  22. #include <GL/glew.h>
  23. #include <GL/glut.h>
  24. #include "readtex.h"
  25. #include "trackball.h"
  26. #define SPECULAR_TEXTURE_FILE "../images/reflect.rgb"
  27. #define BASE_TEXTURE_FILE "../images/tile.rgb"
  28. /* Menu items */
  29. #define DO_SPEC_TEXTURE 1
  30. #define OBJECT 2
  31. #define ANIMATE 3
  32. #define QUIT 100
  33. /* for convolution */
  34. #define FILTER_SIZE 7
  35. static GLint WinWidth = 500, WinHeight = 500;
  36. static GLuint CylinderObj = 0;
  37. static GLuint TeapotObj = 0;
  38. static GLuint Object = 0;
  39. static GLboolean Animate = GL_TRUE;
  40. static float CurQuat[4] = { 0, 0, 0, 1 };
  41. static GLfloat Black[4] = { 0, 0, 0, 0 };
  42. static GLfloat White[4] = { 1, 1, 1, 1 };
  43. static GLfloat Diffuse[4] = { .3, .3, 1.0, 1.0 }; /* blue */
  44. static GLfloat Shininess = 6;
  45. static GLuint BaseTexture, SpecularTexture;
  46. static GLboolean DoSpecTexture = GL_TRUE;
  47. static GLboolean ButtonDown = GL_FALSE;
  48. static GLint ButtonX, ButtonY;
  49. /* performance info */
  50. static GLint T0 = 0;
  51. static GLint Frames = 0;
  52. static void Idle( void )
  53. {
  54. static const float yAxis[3] = {0, 1, 0};
  55. static double t0 = -1.;
  56. float quat[4];
  57. double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  58. if (t0 < 0.0)
  59. t0 = t;
  60. dt = t - t0;
  61. t0 = t;
  62. axis_to_quat(yAxis, 2.0 * dt, quat);
  63. add_quats(quat, CurQuat, CurQuat);
  64. glutPostRedisplay();
  65. }
  66. static void Display( void )
  67. {
  68. GLfloat rot[4][4];
  69. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  70. glPushMatrix();
  71. build_rotmatrix(rot, CurQuat);
  72. glMultMatrixf(&rot[0][0]);
  73. /* First pass: diffuse lighting with base texture */
  74. glMaterialfv(GL_FRONT, GL_DIFFUSE, Diffuse);
  75. glMaterialfv(GL_FRONT, GL_SPECULAR, Black);
  76. glEnable(GL_TEXTURE_2D);
  77. glBindTexture(GL_TEXTURE_2D, BaseTexture);
  78. glCallList(Object);
  79. /* Second pass: specular lighting with reflection texture */
  80. glEnable(GL_POLYGON_OFFSET_FILL);
  81. glBlendFunc(GL_ONE, GL_ONE); /* add */
  82. glEnable(GL_BLEND);
  83. glMaterialfv(GL_FRONT, GL_DIFFUSE, Black);
  84. glMaterialfv(GL_FRONT, GL_SPECULAR, White);
  85. if (DoSpecTexture) {
  86. glBindTexture(GL_TEXTURE_2D, SpecularTexture);
  87. glEnable(GL_TEXTURE_GEN_S);
  88. glEnable(GL_TEXTURE_GEN_T);
  89. }
  90. else {
  91. glDisable(GL_TEXTURE_2D);
  92. }
  93. glCallList(Object);
  94. glDisable(GL_TEXTURE_GEN_S);
  95. glDisable(GL_TEXTURE_GEN_T);
  96. glDisable(GL_BLEND);
  97. glDisable(GL_POLYGON_OFFSET_FILL);
  98. glPopMatrix();
  99. glutSwapBuffers();
  100. if (Animate) {
  101. GLint t = glutGet(GLUT_ELAPSED_TIME);
  102. Frames++;
  103. if (t - T0 >= 5000) {
  104. GLfloat seconds = (t - T0) / 1000.0;
  105. GLfloat fps = Frames / seconds;
  106. printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
  107. fflush(stdout);
  108. T0 = t;
  109. Frames = 0;
  110. }
  111. }
  112. }
  113. static void Reshape( int width, int height )
  114. {
  115. GLfloat h = 30.0;
  116. GLfloat w = h * width / height;
  117. WinWidth = width;
  118. WinHeight = height;
  119. glViewport( 0, 0, width, height );
  120. glMatrixMode( GL_PROJECTION );
  121. glLoadIdentity();
  122. glFrustum( -w, w, -h, h, 150.0, 500.0 );
  123. glMatrixMode( GL_MODELVIEW );
  124. glLoadIdentity();
  125. glTranslatef( 0.0, 0.0, -380.0 );
  126. }
  127. static void ToggleAnimate(void)
  128. {
  129. Animate = !Animate;
  130. if (Animate) {
  131. glutIdleFunc( Idle );
  132. T0 = glutGet(GLUT_ELAPSED_TIME);
  133. Frames = 0;
  134. }
  135. else {
  136. glutIdleFunc( NULL );
  137. }
  138. }
  139. static void ModeMenu(int entry)
  140. {
  141. if (entry==ANIMATE) {
  142. ToggleAnimate();
  143. }
  144. else if (entry==DO_SPEC_TEXTURE) {
  145. DoSpecTexture = !DoSpecTexture;
  146. }
  147. else if (entry==OBJECT) {
  148. if (Object == TeapotObj)
  149. Object = CylinderObj;
  150. else
  151. Object = TeapotObj;
  152. }
  153. else if (entry==QUIT) {
  154. exit(0);
  155. }
  156. glutPostRedisplay();
  157. }
  158. static void Key( unsigned char key, int x, int y )
  159. {
  160. (void) x;
  161. (void) y;
  162. switch (key) {
  163. case 's':
  164. Shininess--;
  165. if (Shininess < 0.0)
  166. Shininess = 0.0;
  167. glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
  168. printf("Shininess = %g\n", Shininess);
  169. break;
  170. case 'S':
  171. Shininess++;
  172. if (Shininess > 128.0)
  173. Shininess = 128.0;
  174. glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
  175. printf("Shininess = %g\n", Shininess);
  176. break;
  177. case 'a':
  178. case ' ':
  179. ToggleAnimate();
  180. break;
  181. case 27:
  182. exit(0);
  183. break;
  184. }
  185. glutPostRedisplay();
  186. }
  187. static void
  188. MouseMotion(int x, int y)
  189. {
  190. if (ButtonDown) {
  191. float x0 = (2.0 * ButtonX - WinWidth) / WinWidth;
  192. float y0 = (WinHeight - 2.0 * ButtonY) / WinHeight;
  193. float x1 = (2.0 * x - WinWidth) / WinWidth;
  194. float y1 = (WinHeight - 2.0 * y) / WinHeight;
  195. float q[4];
  196. trackball(q, x0, y0, x1, y1);
  197. ButtonX = x;
  198. ButtonY = y;
  199. add_quats(q, CurQuat, CurQuat);
  200. glutPostRedisplay();
  201. }
  202. }
  203. static void
  204. MouseButton(int button, int state, int x, int y)
  205. {
  206. if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  207. ButtonDown = GL_TRUE;
  208. ButtonX = x;
  209. ButtonY = y;
  210. }
  211. else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  212. ButtonDown = GL_FALSE;
  213. }
  214. }
  215. static void Init( int argc, char *argv[] )
  216. {
  217. GLboolean convolve = GL_FALSE;
  218. GLboolean fullscreen = GL_FALSE;
  219. int i;
  220. for (i = 1; i < argc; i++) {
  221. if (strcmp(argv[i], "-info")==0) {
  222. printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
  223. printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
  224. printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
  225. printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
  226. }
  227. else if (strcmp(argv[i], "-c")==0) {
  228. convolve = GL_TRUE;
  229. }
  230. else if (strcmp(argv[i], "-f")==0) {
  231. fullscreen = GL_TRUE;
  232. }
  233. }
  234. if (fullscreen)
  235. glutFullScreen();
  236. /* Cylinder object */
  237. {
  238. static GLfloat height = 100.0;
  239. static GLfloat radius = 40.0;
  240. static GLint slices = 24; /* pie slices around Z axis */
  241. static GLint stacks = 10; /* subdivisions along length of cylinder */
  242. static GLint rings = 4; /* rings in the end disks */
  243. GLUquadricObj *q = gluNewQuadric();
  244. assert(q);
  245. gluQuadricTexture(q, GL_TRUE);
  246. CylinderObj = glGenLists(1);
  247. glNewList(CylinderObj, GL_COMPILE);
  248. glPushMatrix();
  249. glTranslatef(0.0, 0.0, -0.5 * height);
  250. glMatrixMode(GL_TEXTURE);
  251. glLoadIdentity();
  252. /*glScalef(8.0, 4.0, 2.0);*/
  253. glMatrixMode(GL_MODELVIEW);
  254. /* cylinder */
  255. gluQuadricNormals(q, GL_SMOOTH);
  256. gluQuadricTexture(q, GL_TRUE);
  257. gluCylinder(q, radius, radius, height, slices, stacks);
  258. /* end cap */
  259. glMatrixMode(GL_TEXTURE);
  260. glLoadIdentity();
  261. glScalef(3.0, 3.0, 1.0);
  262. glMatrixMode(GL_MODELVIEW);
  263. glTranslatef(0.0, 0.0, height);
  264. gluDisk(q, 0.0, radius, slices, rings);
  265. /* other end cap */
  266. glTranslatef(0.0, 0.0, -height);
  267. gluQuadricOrientation(q, GLU_INSIDE);
  268. gluDisk(q, 0.0, radius, slices, rings);
  269. glPopMatrix();
  270. glMatrixMode(GL_TEXTURE);
  271. glLoadIdentity();
  272. glMatrixMode(GL_MODELVIEW);
  273. glEndList();
  274. gluDeleteQuadric(q);
  275. }
  276. /* Teapot */
  277. {
  278. TeapotObj = glGenLists(1);
  279. glNewList(TeapotObj, GL_COMPILE);
  280. glFrontFace(GL_CW);
  281. glutSolidTeapot(40.0);
  282. glFrontFace(GL_CCW);
  283. glEndList();
  284. }
  285. /* show cylinder by default */
  286. Object = CylinderObj;
  287. /* lighting */
  288. glEnable(GL_LIGHTING);
  289. {
  290. GLfloat pos[4] = { 3, 3, 3, 1 };
  291. glLightfv(GL_LIGHT0, GL_AMBIENT, Black);
  292. glLightfv(GL_LIGHT0, GL_DIFFUSE, White);
  293. glLightfv(GL_LIGHT0, GL_SPECULAR, White);
  294. glLightfv(GL_LIGHT0, GL_POSITION, pos);
  295. glEnable(GL_LIGHT0);
  296. glMaterialfv(GL_FRONT, GL_AMBIENT, Black);
  297. glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
  298. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  299. }
  300. /* Base texture */
  301. glGenTextures(1, &BaseTexture);
  302. glBindTexture(GL_TEXTURE_2D, BaseTexture);
  303. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  304. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  305. if (!LoadRGBMipmaps(BASE_TEXTURE_FILE, GL_RGB)) {
  306. printf("Error: couldn't load texture image file %s\n", BASE_TEXTURE_FILE);
  307. exit(1);
  308. }
  309. /* Specular texture */
  310. glGenTextures(1, &SpecularTexture);
  311. glBindTexture(GL_TEXTURE_2D, SpecularTexture);
  312. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  313. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  314. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  315. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  316. if (convolve) {
  317. /* use convolution to blur the texture to simulate a dull finish
  318. * on the object.
  319. */
  320. GLubyte *img;
  321. GLenum format;
  322. GLint w, h;
  323. GLfloat filter[FILTER_SIZE][FILTER_SIZE][4];
  324. for (h = 0; h < FILTER_SIZE; h++) {
  325. for (w = 0; w < FILTER_SIZE; w++) {
  326. const GLfloat k = 1.0 / (FILTER_SIZE * FILTER_SIZE);
  327. filter[h][w][0] = k;
  328. filter[h][w][1] = k;
  329. filter[h][w][2] = k;
  330. filter[h][w][3] = k;
  331. }
  332. }
  333. glEnable(GL_CONVOLUTION_2D);
  334. glConvolutionParameteri(GL_CONVOLUTION_2D,
  335. GL_CONVOLUTION_BORDER_MODE, GL_CONSTANT_BORDER);
  336. glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_RGBA,
  337. FILTER_SIZE, FILTER_SIZE,
  338. GL_RGBA, GL_FLOAT, filter);
  339. img = LoadRGBImage(SPECULAR_TEXTURE_FILE, &w, &h, &format);
  340. if (!img) {
  341. printf("Error: couldn't load texture image file %s\n",
  342. SPECULAR_TEXTURE_FILE);
  343. exit(1);
  344. }
  345. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
  346. format, GL_UNSIGNED_BYTE, img);
  347. free(img);
  348. }
  349. else {
  350. /* regular path */
  351. if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE, GL_RGB)) {
  352. printf("Error: couldn't load texture image file %s\n",
  353. SPECULAR_TEXTURE_FILE);
  354. exit(1);
  355. }
  356. }
  357. /* misc */
  358. glEnable(GL_CULL_FACE);
  359. glEnable(GL_TEXTURE_2D);
  360. glEnable(GL_DEPTH_TEST);
  361. glEnable(GL_NORMALIZE);
  362. glPolygonOffset( -1, -1 );
  363. }
  364. int main( int argc, char *argv[] )
  365. {
  366. glutInitWindowSize(WinWidth, WinHeight);
  367. glutInit( &argc, argv );
  368. glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
  369. glutCreateWindow(argv[0] );
  370. glewInit();
  371. glutReshapeFunc( Reshape );
  372. glutKeyboardFunc( Key );
  373. glutDisplayFunc( Display );
  374. glutMotionFunc(MouseMotion);
  375. glutMouseFunc(MouseButton);
  376. if (Animate)
  377. glutIdleFunc( Idle );
  378. glutCreateMenu(ModeMenu);
  379. glutAddMenuEntry("Toggle Highlight", DO_SPEC_TEXTURE);
  380. glutAddMenuEntry("Toggle Object", OBJECT);
  381. glutAddMenuEntry("Toggle Animate", ANIMATE);
  382. glutAddMenuEntry("Quit", QUIT);
  383. glutAttachMenu(GLUT_RIGHT_BUTTON);
  384. Init(argc, argv);
  385. glutMainLoop();
  386. return 0;
  387. }