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.

texdemo1.c 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /**
  2. * Test texturing with GL shading language.
  3. *
  4. * Copyright (C) 2007 Brian Paul All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the "Software"),
  8. * to deal in the Software without restriction, including without limitation
  9. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the
  11. * Software is furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included
  14. * in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  20. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <assert.h>
  24. #include <math.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include "GL/glut.h"
  29. #include "readtex.h"
  30. #include "extfuncs.h"
  31. static const char *Demo = "texdemo1";
  32. static const char *ReflectVertFile = "reflect.vert.txt";
  33. static const char *CubeFragFile = "cubemap.frag.txt";
  34. static const char *SimpleVertFile = "simple.vert.txt";
  35. static const char *SimpleTexFragFile = "shadowtex.frag.txt";
  36. static const char *GroundImage = "../images/tile.rgb";
  37. static GLuint Program1, Program2;
  38. static GLfloat TexXrot = 0, TexYrot = 0;
  39. static GLfloat Xrot = 20.0, Yrot = 20.0, Zrot = 0.0;
  40. static GLfloat EyeDist = 10;
  41. static GLboolean Anim = GL_TRUE;
  42. struct uniform_info {
  43. const char *name;
  44. GLuint size;
  45. GLint location;
  46. GLenum type; /**< GL_FLOAT or GL_INT */
  47. GLfloat value[4];
  48. };
  49. static struct uniform_info ReflectUniforms[] = {
  50. { "cubeTex", 1, -1, GL_INT, { 0, 0, 0, 0 } },
  51. { "lightPos", 3, -1, GL_FLOAT, { 10, 10, 20, 0 } },
  52. { NULL, 0, 0, 0, { 0, 0, 0, 0 } }
  53. };
  54. static struct uniform_info SimpleUniforms[] = {
  55. { "tex2d", 1, -1, GL_INT, { 1, 0, 0, 0 } },
  56. { "lightPos", 3, -1, GL_FLOAT, { 10, 10, 20, 0 } },
  57. { NULL, 0, 0, 0, { 0, 0, 0, 0 } }
  58. };
  59. static void
  60. CheckError(int line)
  61. {
  62. GLenum err = glGetError();
  63. if (err) {
  64. printf("GL Error %s (0x%x) at line %d\n",
  65. gluErrorString(err), (int) err, line);
  66. }
  67. }
  68. static void
  69. DrawGround(GLfloat size)
  70. {
  71. glPushMatrix();
  72. glRotatef(90, 1, 0, 0);
  73. glNormal3f(0, 0, 1);
  74. glBegin(GL_POLYGON);
  75. glTexCoord2f(-2, -2); glVertex2f(-size, -size);
  76. glTexCoord2f( 2, -2); glVertex2f( size, -size);
  77. glTexCoord2f( 2, 2); glVertex2f( size, size);
  78. glTexCoord2f(-2, 2); glVertex2f(-size, size);
  79. glEnd();
  80. glPopMatrix();
  81. }
  82. static void
  83. draw(void)
  84. {
  85. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  86. glEnable(GL_TEXTURE_2D);
  87. glPushMatrix(); /* modelview matrix */
  88. glTranslatef(0.0, 0.0, -EyeDist);
  89. glRotatef(Xrot, 1, 0, 0);
  90. glRotatef(Yrot, 0, 1, 0);
  91. glRotatef(Zrot, 0, 0, 1);
  92. /* sphere w/ reflection map */
  93. glPushMatrix();
  94. glTranslatef(0, 1, 0);
  95. glUseProgram_func(Program1);
  96. /* setup texture matrix */
  97. glActiveTexture(GL_TEXTURE0);
  98. glMatrixMode(GL_TEXTURE);
  99. glLoadIdentity();
  100. glRotatef(-TexYrot, 0, 1, 0);
  101. glRotatef(-TexXrot, 1, 0, 0);
  102. glEnable(GL_TEXTURE_GEN_S);
  103. glEnable(GL_TEXTURE_GEN_T);
  104. glEnable(GL_TEXTURE_GEN_R);
  105. glutSolidSphere(2.0, 20, 20);
  106. glLoadIdentity(); /* texture matrix */
  107. glMatrixMode(GL_MODELVIEW);
  108. glPopMatrix();
  109. /* ground */
  110. glUseProgram_func(Program2);
  111. glTranslatef(0, -1.0, 0);
  112. DrawGround(5);
  113. glPopMatrix();
  114. glutSwapBuffers();
  115. }
  116. static void
  117. idle(void)
  118. {
  119. GLfloat t = 0.05 * glutGet(GLUT_ELAPSED_TIME);
  120. TexYrot = t;
  121. glutPostRedisplay();
  122. }
  123. static void
  124. key(unsigned char k, int x, int y)
  125. {
  126. (void) x;
  127. (void) y;
  128. switch (k) {
  129. case ' ':
  130. case 'a':
  131. Anim = !Anim;
  132. if (Anim)
  133. glutIdleFunc(idle);
  134. else
  135. glutIdleFunc(NULL);
  136. break;
  137. case 'z':
  138. EyeDist -= 0.5;
  139. if (EyeDist < 6.0)
  140. EyeDist = 6.0;
  141. break;
  142. case 'Z':
  143. EyeDist += 0.5;
  144. if (EyeDist > 90.0)
  145. EyeDist = 90;
  146. break;
  147. case 27:
  148. exit(0);
  149. }
  150. glutPostRedisplay();
  151. }
  152. static void
  153. specialkey(int key, int x, int y)
  154. {
  155. GLfloat step = 2.0;
  156. (void) x;
  157. (void) y;
  158. switch (key) {
  159. case GLUT_KEY_UP:
  160. Xrot += step;
  161. break;
  162. case GLUT_KEY_DOWN:
  163. Xrot -= step;
  164. break;
  165. case GLUT_KEY_LEFT:
  166. Yrot -= step;
  167. break;
  168. case GLUT_KEY_RIGHT:
  169. Yrot += step;
  170. break;
  171. }
  172. glutPostRedisplay();
  173. }
  174. /* new window size or exposure */
  175. static void
  176. Reshape(int width, int height)
  177. {
  178. GLfloat ar = (float) width / (float) height;
  179. glViewport(0, 0, (GLint)width, (GLint)height);
  180. glMatrixMode(GL_PROJECTION);
  181. glLoadIdentity();
  182. glFrustum(-2.0*ar, 2.0*ar, -2.0, 2.0, 4.0, 100.0);
  183. glMatrixMode(GL_MODELVIEW);
  184. glLoadIdentity();
  185. }
  186. static void
  187. InitCheckers(void)
  188. {
  189. #define CUBE_TEX_SIZE 64
  190. GLubyte image[CUBE_TEX_SIZE][CUBE_TEX_SIZE][3];
  191. static const GLubyte colors[6][3] = {
  192. { 255, 0, 0 }, /* face 0 - red */
  193. { 0, 255, 255 }, /* face 1 - cyan */
  194. { 0, 255, 0 }, /* face 2 - green */
  195. { 255, 0, 255 }, /* face 3 - purple */
  196. { 0, 0, 255 }, /* face 4 - blue */
  197. { 255, 255, 0 } /* face 5 - yellow */
  198. };
  199. static const GLenum targets[6] = {
  200. GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
  201. GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
  202. GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
  203. GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
  204. GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
  205. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
  206. };
  207. GLint i, j, f;
  208. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  209. /* make colored checkerboard cube faces */
  210. for (f = 0; f < 6; f++) {
  211. for (i = 0; i < CUBE_TEX_SIZE; i++) {
  212. for (j = 0; j < CUBE_TEX_SIZE; j++) {
  213. if ((i/4 + j/4) & 1) {
  214. image[i][j][0] = colors[f][0];
  215. image[i][j][1] = colors[f][1];
  216. image[i][j][2] = colors[f][2];
  217. }
  218. else {
  219. image[i][j][0] = 255;
  220. image[i][j][1] = 255;
  221. image[i][j][2] = 255;
  222. }
  223. }
  224. }
  225. glTexImage2D(targets[f], 0, GL_RGB, CUBE_TEX_SIZE, CUBE_TEX_SIZE, 0,
  226. GL_RGB, GL_UNSIGNED_BYTE, image);
  227. }
  228. }
  229. static void
  230. LoadFace(GLenum target, const char *filename,
  231. GLboolean flipTB, GLboolean flipLR)
  232. {
  233. GLint w, h;
  234. GLenum format;
  235. GLubyte *img = LoadRGBImage(filename, &w, &h, &format);
  236. if (!img) {
  237. printf("Error: couldn't load texture image %s\n", filename);
  238. exit(1);
  239. }
  240. assert(format == GL_RGB);
  241. /* <sigh> the way the texture cube mapping works, we have to flip
  242. * images to make things look right.
  243. */
  244. if (flipTB) {
  245. const int stride = 3 * w;
  246. GLubyte temp[3*1024];
  247. int i;
  248. for (i = 0; i < h / 2; i++) {
  249. memcpy(temp, img + i * stride, stride);
  250. memcpy(img + i * stride, img + (h - i - 1) * stride, stride);
  251. memcpy(img + (h - i - 1) * stride, temp, stride);
  252. }
  253. }
  254. if (flipLR) {
  255. const int stride = 3 * w;
  256. GLubyte temp[3];
  257. GLubyte *row;
  258. int i, j;
  259. for (i = 0; i < h; i++) {
  260. row = img + i * stride;
  261. for (j = 0; j < w / 2; j++) {
  262. int k = w - j - 1;
  263. temp[0] = row[j*3+0];
  264. temp[1] = row[j*3+1];
  265. temp[2] = row[j*3+2];
  266. row[j*3+0] = row[k*3+0];
  267. row[j*3+1] = row[k*3+1];
  268. row[j*3+2] = row[k*3+2];
  269. row[k*3+0] = temp[0];
  270. row[k*3+1] = temp[1];
  271. row[k*3+2] = temp[2];
  272. }
  273. }
  274. }
  275. gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img);
  276. free(img);
  277. }
  278. static void
  279. LoadEnvmaps(void)
  280. {
  281. LoadFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, "right.rgb", GL_TRUE, GL_FALSE);
  282. LoadFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, "left.rgb", GL_TRUE, GL_FALSE);
  283. LoadFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, "top.rgb", GL_FALSE, GL_TRUE);
  284. LoadFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, "bottom.rgb", GL_FALSE, GL_TRUE);
  285. LoadFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, "front.rgb", GL_TRUE, GL_FALSE);
  286. LoadFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, "back.rgb", GL_TRUE, GL_FALSE);
  287. }
  288. static void
  289. InitTextures(GLboolean useImageFiles)
  290. {
  291. GLenum filter;
  292. /*
  293. * Env map
  294. */
  295. glActiveTexture(GL_TEXTURE0);
  296. glBindTexture(GL_TEXTURE_CUBE_MAP, 1);
  297. if (useImageFiles) {
  298. LoadEnvmaps();
  299. filter = GL_LINEAR;
  300. }
  301. else {
  302. InitCheckers();
  303. filter = GL_NEAREST;
  304. }
  305. glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, filter);
  306. glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, filter);
  307. glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  308. glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  309. /*
  310. * Ground texture
  311. */
  312. {
  313. GLint imgWidth, imgHeight;
  314. GLenum imgFormat;
  315. GLubyte *image = NULL;
  316. image = LoadRGBImage(GroundImage, &imgWidth, &imgHeight, &imgFormat);
  317. if (!image) {
  318. printf("Couldn't read %s\n", GroundImage);
  319. exit(0);
  320. }
  321. glActiveTexture(GL_TEXTURE1);
  322. glBindTexture(GL_TEXTURE_2D, 2);
  323. gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
  324. imgFormat, GL_UNSIGNED_BYTE, image);
  325. free(image);
  326. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  327. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  328. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  329. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  330. }
  331. }
  332. static void
  333. LoadAndCompileShader(GLuint shader, const char *text)
  334. {
  335. GLint stat;
  336. glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
  337. glCompileShader_func(shader);
  338. glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
  339. if (!stat) {
  340. GLchar log[1000];
  341. GLsizei len;
  342. glGetShaderInfoLog_func(shader, 1000, &len, log);
  343. fprintf(stderr, "%s: problem compiling shader: %s\n", Demo, log);
  344. exit(1);
  345. }
  346. else {
  347. printf("Shader compiled OK\n");
  348. }
  349. }
  350. /**
  351. * Read a shader from a file.
  352. */
  353. static void
  354. ReadShader(GLuint shader, const char *filename)
  355. {
  356. const int max = 100*1000;
  357. int n;
  358. char *buffer = (char*) malloc(max);
  359. FILE *f = fopen(filename, "r");
  360. if (!f) {
  361. fprintf(stderr, "%s: Unable to open shader file %s\n", Demo, filename);
  362. exit(1);
  363. }
  364. n = fread(buffer, 1, max, f);
  365. printf("%s: read %d bytes from shader file %s\n", Demo, n, filename);
  366. if (n > 0) {
  367. buffer[n] = 0;
  368. LoadAndCompileShader(shader, buffer);
  369. }
  370. fclose(f);
  371. free(buffer);
  372. }
  373. static void
  374. CheckLink(GLuint prog)
  375. {
  376. GLint stat;
  377. glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
  378. if (!stat) {
  379. GLchar log[1000];
  380. GLsizei len;
  381. glGetProgramInfoLog_func(prog, 1000, &len, log);
  382. fprintf(stderr, "Linker error:\n%s\n", log);
  383. }
  384. else {
  385. fprintf(stderr, "Link success!\n");
  386. }
  387. }
  388. static GLuint
  389. CreateProgram(const char *vertProgFile, const char *fragProgFile,
  390. struct uniform_info *uniforms)
  391. {
  392. GLuint fragShader = 0, vertShader = 0, program = 0;
  393. GLint i;
  394. program = glCreateProgram_func();
  395. if (vertProgFile) {
  396. vertShader = glCreateShader_func(GL_VERTEX_SHADER);
  397. ReadShader(vertShader, vertProgFile);
  398. glAttachShader_func(program, vertShader);
  399. }
  400. if (fragProgFile) {
  401. fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
  402. ReadShader(fragShader, fragProgFile);
  403. glAttachShader_func(program, fragShader);
  404. }
  405. glLinkProgram_func(program);
  406. CheckLink(program);
  407. glUseProgram_func(program);
  408. assert(glIsProgram_func(program));
  409. assert(glIsShader_func(fragShader));
  410. assert(glIsShader_func(vertShader));
  411. CheckError(__LINE__);
  412. for (i = 0; uniforms[i].name; i++) {
  413. uniforms[i].location
  414. = glGetUniformLocation_func(program, uniforms[i].name);
  415. printf("Uniform %s location: %d\n", uniforms[i].name,
  416. uniforms[i].location);
  417. switch (uniforms[i].size) {
  418. case 1:
  419. if (uniforms[i].type == GL_INT)
  420. glUniform1i_func(uniforms[i].location,
  421. (GLint) uniforms[i].value[0]);
  422. else
  423. glUniform1fv_func(uniforms[i].location, 1, uniforms[i].value);
  424. break;
  425. case 2:
  426. glUniform2fv_func(uniforms[i].location, 1, uniforms[i].value);
  427. break;
  428. case 3:
  429. glUniform3fv_func(uniforms[i].location, 1, uniforms[i].value);
  430. break;
  431. case 4:
  432. glUniform4fv_func(uniforms[i].location, 1, uniforms[i].value);
  433. break;
  434. default:
  435. abort();
  436. }
  437. }
  438. CheckError(__LINE__);
  439. return program;
  440. }
  441. static void
  442. InitPrograms(void)
  443. {
  444. Program1 = CreateProgram(ReflectVertFile, CubeFragFile, ReflectUniforms);
  445. Program2 = CreateProgram(SimpleVertFile, SimpleTexFragFile, SimpleUniforms);
  446. }
  447. static void
  448. Init(GLboolean useImageFiles)
  449. {
  450. const char *version = (const char *) glGetString(GL_VERSION);
  451. if (version[0] != '2' || version[1] != '.') {
  452. printf("Warning: this program expects OpenGL 2.0\n");
  453. /*exit(1);*/
  454. }
  455. printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
  456. GetExtensionFuncs();
  457. InitTextures(useImageFiles);
  458. InitPrograms();
  459. glEnable(GL_DEPTH_TEST);
  460. glClearColor(.6, .6, .9, 0);
  461. glColor3f(1.0, 1.0, 1.0);
  462. }
  463. int
  464. main(int argc, char *argv[])
  465. {
  466. glutInit(&argc, argv);
  467. glutInitWindowSize(500, 400);
  468. glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
  469. glutCreateWindow(Demo);
  470. glutReshapeFunc(Reshape);
  471. glutKeyboardFunc(key);
  472. glutSpecialFunc(specialkey);
  473. glutDisplayFunc(draw);
  474. if (Anim)
  475. glutIdleFunc(idle);
  476. if (argc > 1 && strcmp(argv[1] , "-i") == 0)
  477. Init(1);
  478. else
  479. Init(0);
  480. glutMainLoop();
  481. return 0;
  482. }