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.

fslight.c 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /**
  2. * Test OpenGL 2.0 vertex/fragment shaders.
  3. * Brian Paul
  4. * 1 November 2006
  5. *
  6. * Based on ARB version by:
  7. * Michal Krol
  8. * 20 February 2006
  9. *
  10. * Based on the original demo by:
  11. * Brian Paul
  12. * 17 April 2003
  13. */
  14. #include <assert.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include <GL/gl.h>
  20. #include <GL/glut.h>
  21. #include <GL/glext.h>
  22. #include "extfuncs.h"
  23. #define TEXTURE 0
  24. static GLint CoordAttrib = 0;
  25. static char *FragProgFile = NULL;
  26. static char *VertProgFile = NULL;
  27. static GLfloat diffuse[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
  28. static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
  29. static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 0.0f };
  30. static GLfloat delta = 1.0f;
  31. static GLuint fragShader;
  32. static GLuint vertShader;
  33. static GLuint program;
  34. static GLint uDiffuse;
  35. static GLint uSpecular;
  36. static GLint uTexture;
  37. static GLuint SphereList, RectList, CurList;
  38. static GLint win = 0;
  39. static GLboolean anim = GL_TRUE;
  40. static GLboolean wire = GL_FALSE;
  41. static GLboolean pixelLight = GL_TRUE;
  42. static GLint t0 = 0;
  43. static GLint frames = 0;
  44. static GLfloat xRot = 90.0f, yRot = 0.0f;
  45. static void
  46. normalize(GLfloat *dst, const GLfloat *src)
  47. {
  48. GLfloat len = sqrt(src[0] * src[0] + src[1] * src[1] + src[2] * src[2]);
  49. dst[0] = src[0] / len;
  50. dst[1] = src[1] / len;
  51. dst[2] = src[2] / len;
  52. dst[3] = src[3];
  53. }
  54. static void
  55. Redisplay(void)
  56. {
  57. GLfloat vec[4];
  58. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  59. /* update light position */
  60. normalize(vec, lightPos);
  61. glLightfv(GL_LIGHT0, GL_POSITION, vec);
  62. if (pixelLight) {
  63. glUseProgram_func(program);
  64. glDisable(GL_LIGHTING);
  65. }
  66. else {
  67. glUseProgram_func(0);
  68. glEnable(GL_LIGHTING);
  69. }
  70. glPushMatrix();
  71. glRotatef(xRot, 1.0f, 0.0f, 0.0f);
  72. glRotatef(yRot, 0.0f, 1.0f, 0.0f);
  73. /*
  74. glutSolidSphere(2.0, 10, 5);
  75. */
  76. glCallList(CurList);
  77. glPopMatrix();
  78. glutSwapBuffers();
  79. frames++;
  80. if (anim) {
  81. GLint t = glutGet(GLUT_ELAPSED_TIME);
  82. if (t - t0 >= 5000) {
  83. GLfloat seconds =(GLfloat)(t - t0) / 1000.0f;
  84. GLfloat fps = frames / seconds;
  85. printf("%d frames in %6.3f seconds = %6.3f FPS\n",
  86. frames, seconds, fps);
  87. t0 = t;
  88. frames = 0;
  89. }
  90. }
  91. }
  92. static void
  93. Idle(void)
  94. {
  95. lightPos[0] += delta;
  96. if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
  97. delta = -delta;
  98. glutPostRedisplay();
  99. }
  100. static void
  101. Reshape(int width, int height)
  102. {
  103. glViewport(0, 0, width, height);
  104. glMatrixMode(GL_PROJECTION);
  105. glLoadIdentity();
  106. glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
  107. glMatrixMode(GL_MODELVIEW);
  108. glLoadIdentity();
  109. glTranslatef(0.0f, 0.0f, -15.0f);
  110. }
  111. static void
  112. CleanUp(void)
  113. {
  114. glDeleteShader_func(fragShader);
  115. glDeleteShader_func(vertShader);
  116. glDeleteProgram_func(program);
  117. glutDestroyWindow(win);
  118. }
  119. static void
  120. Key(unsigned char key, int x, int y)
  121. {
  122. (void) x;
  123. (void) y;
  124. switch(key) {
  125. case ' ':
  126. case 'a':
  127. anim = !anim;
  128. if (anim)
  129. glutIdleFunc(Idle);
  130. else
  131. glutIdleFunc(NULL);
  132. break;
  133. case 'x':
  134. lightPos[0] -= 1.0f;
  135. break;
  136. case 'X':
  137. lightPos[0] += 1.0f;
  138. break;
  139. case 'w':
  140. wire = !wire;
  141. if (wire)
  142. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  143. else
  144. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  145. break;
  146. case 'o':
  147. if (CurList == SphereList)
  148. CurList = RectList;
  149. else
  150. CurList = SphereList;
  151. break;
  152. case 'p':
  153. pixelLight = !pixelLight;
  154. if (pixelLight)
  155. printf("Per-pixel lighting\n");
  156. else
  157. printf("Conventional lighting\n");
  158. break;
  159. case 27:
  160. CleanUp();
  161. exit(0);
  162. break;
  163. }
  164. glutPostRedisplay();
  165. }
  166. static void
  167. SpecialKey(int key, int x, int y)
  168. {
  169. const GLfloat step = 3.0f;
  170. (void) x;
  171. (void) y;
  172. switch(key) {
  173. case GLUT_KEY_UP:
  174. xRot -= step;
  175. break;
  176. case GLUT_KEY_DOWN:
  177. xRot += step;
  178. break;
  179. case GLUT_KEY_LEFT:
  180. yRot -= step;
  181. break;
  182. case GLUT_KEY_RIGHT:
  183. yRot += step;
  184. break;
  185. }
  186. glutPostRedisplay();
  187. }
  188. static void
  189. TestFunctions(void)
  190. {
  191. printf("Error 0x%x at line %d\n", glGetError(), __LINE__);
  192. assert(glIsProgram_func(program));
  193. assert(glIsShader_func(fragShader));
  194. assert(glIsShader_func(vertShader));
  195. /* attached shaders */
  196. {
  197. GLuint shaders[20];
  198. GLsizei count;
  199. int i;
  200. glGetAttachedShaders_func(program, 20, &count, shaders);
  201. for (i = 0; i < count; i++) {
  202. printf("Attached: %u\n", shaders[i]);
  203. assert(shaders[i] == fragShader ||
  204. shaders[i] == vertShader);
  205. }
  206. }
  207. {
  208. GLchar log[1000];
  209. GLsizei len;
  210. glGetShaderInfoLog_func(vertShader, 1000, &len, log);
  211. printf("Vert Shader Info Log: %s\n", log);
  212. glGetShaderInfoLog_func(fragShader, 1000, &len, log);
  213. printf("Frag Shader Info Log: %s\n", log);
  214. glGetProgramInfoLog_func(program, 1000, &len, log);
  215. printf("Program Info Log: %s\n", log);
  216. }
  217. /* active uniforms */
  218. {
  219. GLint n, max, i;
  220. glGetProgramiv_func(program, GL_ACTIVE_UNIFORMS, &n);
  221. glGetProgramiv_func(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max);
  222. printf("Num uniforms: %d Max name length: %d\n", n, max);
  223. for (i = 0; i < n; i++) {
  224. GLint size, len;
  225. GLenum type;
  226. char name[100];
  227. glGetActiveUniform_func(program, i, 100, &len, &size, &type, name);
  228. printf(" %d: %s nameLen=%d size=%d type=0x%x\n",
  229. i, name, len, size, type);
  230. }
  231. }
  232. }
  233. #if TEXTURE
  234. static void
  235. MakeTexture(void)
  236. {
  237. #define SZ0 64
  238. #define SZ1 32
  239. GLubyte image0[SZ0][SZ0][SZ0][4];
  240. GLubyte image1[SZ1][SZ1][SZ1][4];
  241. GLuint i, j, k;
  242. /* level 0: two-tone gray checkboard */
  243. for (i = 0; i < SZ0; i++) {
  244. for (j = 0; j < SZ0; j++) {
  245. for (k = 0; k < SZ0; k++) {
  246. if ((i/8 + j/8 + k/8) & 1) {
  247. image0[i][j][k][0] =
  248. image0[i][j][k][1] =
  249. image0[i][j][k][2] = 200;
  250. }
  251. else {
  252. image0[i][j][k][0] =
  253. image0[i][j][k][1] =
  254. image0[i][j][k][2] = 100;
  255. }
  256. image0[i][j][k][3] = 255;
  257. }
  258. }
  259. }
  260. /* level 1: two-tone green checkboard */
  261. for (i = 0; i < SZ1; i++) {
  262. for (j = 0; j < SZ1; j++) {
  263. for (k = 0; k < SZ1; k++) {
  264. if ((i/8 + j/8 + k/8) & 1) {
  265. image1[i][j][k][0] = 0;
  266. image1[i][j][k][1] = 250;
  267. image1[i][j][k][2] = 0;
  268. }
  269. else {
  270. image1[i][j][k][0] = 0;
  271. image1[i][j][k][1] = 200;
  272. image1[i][j][k][2] = 0;
  273. }
  274. image1[i][j][k][3] = 255;
  275. }
  276. }
  277. }
  278. glActiveTexture(GL_TEXTURE2); /* unit 2 */
  279. glBindTexture(GL_TEXTURE_2D, 42);
  280. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ0, SZ0, 0,
  281. GL_RGBA, GL_UNSIGNED_BYTE, image0);
  282. glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, SZ1, SZ1, 0,
  283. GL_RGBA, GL_UNSIGNED_BYTE, image1);
  284. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
  285. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  286. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  287. glActiveTexture(GL_TEXTURE4); /* unit 4 */
  288. glBindTexture(GL_TEXTURE_3D, 43);
  289. glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, SZ0, SZ0, SZ0, 0,
  290. GL_RGBA, GL_UNSIGNED_BYTE, image0);
  291. glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA, SZ1, SZ1, SZ1, 0,
  292. GL_RGBA, GL_UNSIGNED_BYTE, image1);
  293. glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
  294. glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  295. glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  296. }
  297. #endif
  298. static void
  299. MakeSphere(void)
  300. {
  301. GLUquadricObj *obj = gluNewQuadric();
  302. SphereList = glGenLists(1);
  303. gluQuadricTexture(obj, GL_TRUE);
  304. glNewList(SphereList, GL_COMPILE);
  305. gluSphere(obj, 2.0f, 10, 5);
  306. glEndList();
  307. }
  308. static void
  309. VertAttrib(GLint index, float x, float y)
  310. {
  311. #if 1
  312. glVertexAttrib2f_func(index, x, y);
  313. #else
  314. glTexCoord2f(x, y);
  315. #endif
  316. }
  317. static void
  318. MakeRect(void)
  319. {
  320. RectList = glGenLists(1);
  321. glNewList(RectList, GL_COMPILE);
  322. glNormal3f(0, 0, 1);
  323. glBegin(GL_POLYGON);
  324. VertAttrib(CoordAttrib, 0, 0); glVertex2f(-2, -2);
  325. VertAttrib(CoordAttrib, 1, 0); glVertex2f( 2, -2);
  326. VertAttrib(CoordAttrib, 1, 1); glVertex2f( 2, 2);
  327. VertAttrib(CoordAttrib, 0, 1); glVertex2f(-2, 2);
  328. glEnd(); /* XXX omit this and crash! */
  329. glEndList();
  330. }
  331. static void
  332. LoadAndCompileShader(GLuint shader, const char *text)
  333. {
  334. GLint stat;
  335. glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
  336. glCompileShader_func(shader);
  337. glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
  338. if (!stat) {
  339. GLchar log[1000];
  340. GLsizei len;
  341. glGetShaderInfoLog_func(shader, 1000, &len, log);
  342. fprintf(stderr, "fslight: problem compiling shader:\n%s\n", log);
  343. exit(1);
  344. }
  345. }
  346. /**
  347. * Read a shader from a file.
  348. */
  349. static void
  350. ReadShader(GLuint shader, const char *filename)
  351. {
  352. const int max = 100*1000;
  353. int n;
  354. char *buffer = (char*) malloc(max);
  355. FILE *f = fopen(filename, "r");
  356. if (!f) {
  357. fprintf(stderr, "fslight: Unable to open shader file %s\n", filename);
  358. exit(1);
  359. }
  360. n = fread(buffer, 1, max, f);
  361. printf("fslight: read %d bytes from shader file %s\n", n, filename);
  362. if (n > 0) {
  363. buffer[n] = 0;
  364. LoadAndCompileShader(shader, buffer);
  365. }
  366. fclose(f);
  367. free(buffer);
  368. }
  369. static void
  370. CheckLink(GLuint prog)
  371. {
  372. GLint stat;
  373. glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
  374. if (!stat) {
  375. GLchar log[1000];
  376. GLsizei len;
  377. glGetProgramInfoLog_func(prog, 1000, &len, log);
  378. fprintf(stderr, "Linker error:\n%s\n", log);
  379. }
  380. }
  381. static void
  382. Init(void)
  383. {
  384. static const char *fragShaderText =
  385. "uniform vec4 diffuse;\n"
  386. "uniform vec4 specular;\n"
  387. "varying vec3 normal;\n"
  388. "void main() {\n"
  389. " // Compute dot product of light direction and normal vector\n"
  390. " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
  391. " normalize(normal)), 0.0);\n"
  392. " // Compute diffuse and specular contributions\n"
  393. " gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0);\n"
  394. "}\n";
  395. static const char *vertShaderText =
  396. "varying vec3 normal;\n"
  397. "void main() {\n"
  398. " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
  399. " normal = gl_NormalMatrix * gl_Normal;\n"
  400. "}\n";
  401. const char *version;
  402. version = (const char *) glGetString(GL_VERSION);
  403. if (version[0] != '2' || version[1] != '.') {
  404. printf("This program requires OpenGL 2.x, found %s\n", version);
  405. exit(1);
  406. }
  407. GetExtensionFuncs();
  408. fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
  409. if (FragProgFile)
  410. ReadShader(fragShader, FragProgFile);
  411. else
  412. LoadAndCompileShader(fragShader, fragShaderText);
  413. vertShader = glCreateShader_func(GL_VERTEX_SHADER);
  414. if (VertProgFile)
  415. ReadShader(vertShader, VertProgFile);
  416. else
  417. LoadAndCompileShader(vertShader, vertShaderText);
  418. program = glCreateProgram_func();
  419. glAttachShader_func(program, fragShader);
  420. glAttachShader_func(program, vertShader);
  421. glLinkProgram_func(program);
  422. CheckLink(program);
  423. glUseProgram_func(program);
  424. uDiffuse = glGetUniformLocation_func(program, "diffuse");
  425. uSpecular = glGetUniformLocation_func(program, "specular");
  426. uTexture = glGetUniformLocation_func(program, "texture");
  427. printf("DiffusePos %d SpecularPos %d TexturePos %d\n",
  428. uDiffuse, uSpecular, uTexture);
  429. glUniform4fv_func(uDiffuse, 1, diffuse);
  430. glUniform4fv_func(uSpecular, 1, specular);
  431. /* assert(glGetError() == 0);*/
  432. #if TEXTURE
  433. glUniform1i_func(uTexture, 2); /* use texture unit 2 */
  434. #endif
  435. /*assert(glGetError() == 0);*/
  436. if (CoordAttrib) {
  437. int i;
  438. glBindAttribLocation_func(program, CoordAttrib, "coord");
  439. i = glGetAttribLocation_func(program, "coord");
  440. assert(i >= 0);
  441. if (i != CoordAttrib) {
  442. printf("Hmmm, NVIDIA bug?\n");
  443. CoordAttrib = i;
  444. }
  445. else {
  446. printf("Mesa bind attrib: coord = %d\n", i);
  447. }
  448. }
  449. /*assert(glGetError() == 0);*/
  450. glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
  451. glEnable(GL_DEPTH_TEST);
  452. glEnable(GL_LIGHT0);
  453. glEnable(GL_LIGHTING);
  454. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
  455. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
  456. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
  457. MakeSphere();
  458. MakeRect();
  459. CurList = SphereList;
  460. #if TEXTURE
  461. MakeTexture();
  462. #endif
  463. printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
  464. printf("Press p to toggle between per-pixel and per-vertex lighting\n");
  465. /* test glGetShaderSource() */
  466. if (0) {
  467. GLsizei len = strlen(fragShaderText) + 1;
  468. GLsizei lenOut;
  469. GLchar *src =(GLchar *) malloc(len * sizeof(GLchar));
  470. glGetShaderSource_func(fragShader, 0, NULL, src);
  471. glGetShaderSource_func(fragShader, len, &lenOut, src);
  472. assert(len == lenOut + 1);
  473. assert(strcmp(src, fragShaderText) == 0);
  474. free(src);
  475. }
  476. assert(glIsProgram_func(program));
  477. assert(glIsShader_func(fragShader));
  478. assert(glIsShader_func(vertShader));
  479. glColor3f(1, 0, 0);
  480. /* for testing state vars */
  481. {
  482. static GLfloat fc[4] = { 1, 1, 0, 0 };
  483. static GLfloat amb[4] = { 1, 0, 1, 0 };
  484. glFogfv(GL_FOG_COLOR, fc);
  485. glLightfv(GL_LIGHT1, GL_AMBIENT, amb);
  486. }
  487. #if 0
  488. TestFunctions();
  489. #else
  490. (void) TestFunctions;
  491. #endif
  492. }
  493. static void
  494. ParseOptions(int argc, char *argv[])
  495. {
  496. int i;
  497. for (i = 1; i < argc; i++) {
  498. if (strcmp(argv[i], "-fs") == 0) {
  499. FragProgFile = argv[i+1];
  500. }
  501. else if (strcmp(argv[i], "-vs") == 0) {
  502. VertProgFile = argv[i+1];
  503. }
  504. }
  505. }
  506. int
  507. main(int argc, char *argv[])
  508. {
  509. glutInit(&argc, argv);
  510. glutInitWindowPosition( 0, 0);
  511. glutInitWindowSize(200, 200);
  512. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  513. win = glutCreateWindow(argv[0]);
  514. glutReshapeFunc(Reshape);
  515. glutKeyboardFunc(Key);
  516. glutSpecialFunc(SpecialKey);
  517. glutDisplayFunc(Redisplay);
  518. if (anim)
  519. glutIdleFunc(Idle);
  520. ParseOptions(argc, argv);
  521. Init();
  522. glutMainLoop();
  523. return 0;
  524. }