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.

twoside.c 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /**
  2. * Test two-sided lighting with shaders.
  3. * Both GL_VERTEX_PROGRAM_TWO_SIDE and gl_FrontFacing can be tested
  4. * (see keys below).
  5. *
  6. * Brian Paul
  7. * 18 Dec 2007
  8. */
  9. #include <assert.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <math.h>
  14. #include <GL/glew.h>
  15. #include <GL/glut.h>
  16. #include "shaderutil.h"
  17. #ifndef M_PI
  18. #define M_PI 3.1415926535
  19. #endif
  20. static GLint WinWidth = 300, WinHeight = 300;
  21. static char *FragProgFile = NULL;
  22. static char *VertProgFile = NULL;
  23. static GLuint fragShader;
  24. static GLuint vertShader;
  25. static GLuint program;
  26. static GLint win = 0;
  27. static GLboolean anim;
  28. static GLboolean DetermineFacingInFragProg;
  29. static GLfloat Xrot;
  30. static GLint u_fragface;
  31. static GLenum FrontWinding;
  32. static int prevTime = 0;
  33. static const GLfloat Red[4] = {1, 0, 0, 1};
  34. static const GLfloat Green[4] = {0, 1, 0, 0};
  35. static void
  36. SetDefaults(void)
  37. {
  38. DetermineFacingInFragProg = GL_TRUE;
  39. FrontWinding = GL_CCW;
  40. Xrot = 30;
  41. anim = 0;
  42. glutIdleFunc(NULL);
  43. }
  44. static void
  45. Redisplay(void)
  46. {
  47. const int sections = 20;
  48. int i;
  49. float radius = 2;
  50. glFrontFace(FrontWinding);
  51. if (DetermineFacingInFragProg) {
  52. glUniform1i(u_fragface, 1);
  53. glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
  54. }
  55. else {
  56. glUniform1i(u_fragface, 0);
  57. glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
  58. }
  59. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  60. glPushMatrix();
  61. glRotatef(Xrot, 1, 0, 0);
  62. /* Draw a tristrip ring */
  63. glBegin(GL_TRIANGLE_STRIP);
  64. glColor4fv(Red);
  65. glSecondaryColor3fv(Green);
  66. for (i = 0; i <= sections; i++) {
  67. float a = (float) i / (sections) * M_PI * 2.0;
  68. float x = radius * cos(a);
  69. float y = radius * sin(a);
  70. glVertex3f(x, -1, y);
  71. glVertex3f(x, +1, y);
  72. }
  73. glEnd();
  74. glPopMatrix();
  75. glutSwapBuffers();
  76. }
  77. static void
  78. Idle(void)
  79. {
  80. int curTime = glutGet(GLUT_ELAPSED_TIME);
  81. int dt = curTime - prevTime;
  82. if (prevTime == 0) {
  83. prevTime = curTime;
  84. return;
  85. }
  86. prevTime = curTime;
  87. Xrot += dt * 0.1;
  88. glutPostRedisplay();
  89. }
  90. static void
  91. Reshape(int width, int height)
  92. {
  93. float ar = (float) width / height;
  94. glViewport(0, 0, width, height);
  95. glMatrixMode(GL_PROJECTION);
  96. glLoadIdentity();
  97. glFrustum(-ar, ar, -1, 1, 3, 25);
  98. glMatrixMode(GL_MODELVIEW);
  99. glLoadIdentity();
  100. glTranslatef(0, 0, -10);
  101. }
  102. static void
  103. CleanUp(void)
  104. {
  105. glDeleteShader(fragShader);
  106. glDeleteShader(vertShader);
  107. glDeleteProgram(program);
  108. glutDestroyWindow(win);
  109. }
  110. static void
  111. Key(unsigned char key, int x, int y)
  112. {
  113. (void) x;
  114. (void) y;
  115. switch(key) {
  116. case ' ':
  117. case 'a':
  118. anim = !anim;
  119. if (anim) {
  120. prevTime = glutGet(GLUT_ELAPSED_TIME);
  121. glutIdleFunc(Idle);
  122. }
  123. else
  124. glutIdleFunc(NULL);
  125. break;
  126. case 'f':
  127. printf("Using frag shader gl_FrontFacing\n");
  128. DetermineFacingInFragProg = GL_TRUE;
  129. break;
  130. case 'v':
  131. printf("Using vert shader Two-sided lighting\n");
  132. DetermineFacingInFragProg = GL_FALSE;
  133. break;
  134. case 'r':
  135. /* reset */
  136. SetDefaults();
  137. break;
  138. case 's':
  139. Xrot += 5;
  140. break;
  141. case 'S':
  142. Xrot -= 5;
  143. break;
  144. case 'w':
  145. if (FrontWinding == GL_CCW) {
  146. FrontWinding = GL_CW;
  147. printf("FrontFace = GL_CW\n");
  148. }
  149. else {
  150. FrontWinding = GL_CCW;
  151. printf("FrontFace = GL_CCW\n");
  152. }
  153. break;
  154. case 27:
  155. CleanUp();
  156. exit(0);
  157. break;
  158. }
  159. glutPostRedisplay();
  160. }
  161. static void
  162. Init(void)
  163. {
  164. static const char *fragShaderText =
  165. "uniform bool fragface; \n"
  166. "void main() { \n"
  167. #if 1
  168. " if (!fragface || gl_FrontFacing) { \n"
  169. " gl_FragColor = gl_Color; \n"
  170. " } \n"
  171. " else { \n"
  172. " // note: dim green to help debug \n"
  173. " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
  174. " } \n"
  175. #else
  176. /* DEBUG CODE */
  177. " bool f = gl_FrontFacing; \n"
  178. " if (f) { \n"
  179. " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0); \n"
  180. " } \n"
  181. " else { \n"
  182. " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0); \n"
  183. " } \n"
  184. #endif
  185. "} \n";
  186. static const char *vertShaderText =
  187. "uniform bool fragface; \n"
  188. "void main() { \n"
  189. " gl_FrontColor = gl_Color; \n"
  190. " if (fragface) { \n"
  191. " // front/back chosen in frag prog \n"
  192. " gl_FrontSecondaryColor = gl_SecondaryColor; \n"
  193. " } \n"
  194. " else { \n"
  195. " // front/back chosen in prim setup \n"
  196. " gl_BackColor = gl_SecondaryColor; \n"
  197. " } \n"
  198. " gl_Position = ftransform(); \n"
  199. "} \n";
  200. if (!ShadersSupported())
  201. exit(1);
  202. vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
  203. fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
  204. program = LinkShaders(vertShader, fragShader);
  205. glUseProgram(program);
  206. u_fragface = glGetUniformLocation(program, "fragface");
  207. printf("Uniforms: %d\n", u_fragface);
  208. /*assert(glGetError() == 0);*/
  209. glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
  210. printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
  211. assert(glIsProgram(program));
  212. assert(glIsShader(fragShader));
  213. assert(glIsShader(vertShader));
  214. glEnable(GL_DEPTH_TEST);
  215. SetDefaults();
  216. }
  217. static void
  218. ParseOptions(int argc, char *argv[])
  219. {
  220. int i;
  221. for (i = 1; i < argc; i++) {
  222. if (strcmp(argv[i], "-fs") == 0) {
  223. FragProgFile = argv[i+1];
  224. }
  225. else if (strcmp(argv[i], "-vs") == 0) {
  226. VertProgFile = argv[i+1];
  227. }
  228. }
  229. }
  230. static void
  231. Usage(void)
  232. {
  233. printf("Keys:\n");
  234. printf(" f - do front/back determination in fragment shader\n");
  235. printf(" v - do front/back determination in vertex shader\n");
  236. printf(" r - reset, show front\n");
  237. printf(" a - toggle animation\n");
  238. printf(" s - step rotation\n");
  239. printf(" w - toggle CW, CCW front-face winding\n");
  240. printf("NOTE: red = front face, green = back face.\n");
  241. }
  242. int
  243. main(int argc, char *argv[])
  244. {
  245. glutInit(&argc, argv);
  246. glutInitWindowSize(WinWidth, WinHeight);
  247. glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
  248. win = glutCreateWindow(argv[0]);
  249. glewInit();
  250. glutReshapeFunc(Reshape);
  251. glutKeyboardFunc(Key);
  252. glutDisplayFunc(Redisplay);
  253. if (anim)
  254. glutIdleFunc(Idle);
  255. ParseOptions(argc, argv);
  256. Init();
  257. Usage();
  258. glutMainLoop();
  259. return 0;
  260. }