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 11KB

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