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.

drawbuffers2.c 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. * Test GL_ARB_draw_buffers2, GL_ARB_draw_buffers, GL_EXT_framebuffer_object
  3. * and GLSL's gl_FragData[].
  4. *
  5. * We draw to two color buffers and show the left half of the first
  6. * color buffer on the left side of the window, and show the right
  7. * half of the second color buffer on the right side of the window.
  8. *
  9. * Different color masks are used for the two color buffers.
  10. * Blending is enabled for the second buffer only.
  11. *
  12. * Brian Paul
  13. * 31 Dec 2009
  14. */
  15. #include <assert.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include <GL/glew.h>
  20. #include <GL/glut.h>
  21. #include "extfuncs.h"
  22. static int Win;
  23. static int Width = 400, Height = 400;
  24. static GLuint FBobject, RBobjects[3];
  25. static GLfloat Xrot = 0.0, Yrot = 0.0;
  26. static GLuint Program;
  27. static GLboolean Anim = GL_TRUE;
  28. static void
  29. CheckError(int line)
  30. {
  31. GLenum err = glGetError();
  32. if (err) {
  33. printf("GL Error 0x%x at line %d\n", (int) err, line);
  34. }
  35. }
  36. static void
  37. Display(void)
  38. {
  39. GLubyte *buffer = malloc(Width * Height * 4);
  40. static const GLenum buffers[2] = {
  41. GL_COLOR_ATTACHMENT0_EXT,
  42. GL_COLOR_ATTACHMENT1_EXT
  43. };
  44. glUseProgram_func(Program);
  45. glEnable(GL_DEPTH_TEST);
  46. /* draw to user framebuffer */
  47. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
  48. /* Clear color buffer 0 (blue) */
  49. glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
  50. glClear(GL_COLOR_BUFFER_BIT);
  51. /* Clear color buffer 1 (1 - blue) */
  52. glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
  53. glClear(GL_COLOR_BUFFER_BIT);
  54. glClear(GL_DEPTH_BUFFER_BIT);
  55. /* draw to two buffers w/ fragment shader */
  56. glDrawBuffersARB(2, buffers);
  57. /* different color masks for each buffer */
  58. if (1) {
  59. glColorMaskIndexedEXT(0, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
  60. glColorMaskIndexedEXT(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
  61. }
  62. glPushMatrix();
  63. glRotatef(Xrot, 1, 0, 0);
  64. glRotatef(Yrot, 0, 1, 0);
  65. glPushMatrix();
  66. glTranslatef(1, 0, 0);
  67. glutSolidTorus(1.0, 2.0, 10, 20);
  68. glPopMatrix();
  69. glPushMatrix();
  70. glTranslatef(-1, 0, 0);
  71. glRotatef(90, 1, 0, 0);
  72. glutSolidTorus(1.0, 2.0, 10, 20);
  73. glPopMatrix();
  74. glPopMatrix();
  75. /* restore default color masks */
  76. glColorMaskIndexedEXT(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  77. glColorMaskIndexedEXT(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  78. /* read from user framebuffer */
  79. /* left half = colorbuffer 0 */
  80. glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
  81. glPixelStorei(GL_PACK_ROW_LENGTH, Width);
  82. glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
  83. glReadPixels(0, 0, Width / 2, Height, GL_RGBA, GL_UNSIGNED_BYTE,
  84. buffer);
  85. /* right half = colorbuffer 1 */
  86. glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
  87. glPixelStorei(GL_PACK_SKIP_PIXELS, Width / 2);
  88. glReadPixels(Width / 2, 0, Width - Width / 2, Height,
  89. GL_RGBA, GL_UNSIGNED_BYTE,
  90. buffer);
  91. /* draw to window */
  92. glUseProgram_func(0);
  93. glDisable(GL_DEPTH_TEST);
  94. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  95. glWindowPos2iARB(0, 0);
  96. glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
  97. free(buffer);
  98. glutSwapBuffers();
  99. CheckError(__LINE__);
  100. }
  101. static void
  102. Idle(void)
  103. {
  104. Xrot = glutGet(GLUT_ELAPSED_TIME) * 0.05;
  105. glutPostRedisplay();
  106. }
  107. static void
  108. Reshape(int width, int height)
  109. {
  110. float ar = (float) width / (float) height;
  111. glViewport(0, 0, width, height);
  112. glMatrixMode(GL_PROJECTION);
  113. glLoadIdentity();
  114. glFrustum(-ar, ar, -1.0, 1.0, 5.0, 35.0);
  115. glMatrixMode(GL_MODELVIEW);
  116. glLoadIdentity();
  117. glTranslatef(0.0, 0.0, -20.0);
  118. Width = width;
  119. Height = height;
  120. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
  121. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
  122. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
  123. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
  124. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
  125. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
  126. Width, Height);
  127. }
  128. static void
  129. CleanUp(void)
  130. {
  131. glDeleteFramebuffersEXT(1, &FBobject);
  132. glDeleteRenderbuffersEXT(3, RBobjects);
  133. glutDestroyWindow(Win);
  134. exit(0);
  135. }
  136. static void
  137. Key(unsigned char key, int x, int y)
  138. {
  139. (void) x;
  140. (void) y;
  141. switch (key) {
  142. case ' ':
  143. Anim = !Anim;
  144. glutIdleFunc(Anim ? Idle : NULL);
  145. break;
  146. case 'x':
  147. Xrot += 5.0;
  148. break;
  149. case 'X':
  150. Xrot -= 5.0;
  151. break;
  152. case 'y':
  153. Yrot += 5.0;
  154. break;
  155. case 'Y':
  156. Yrot -= 5.0;
  157. break;
  158. case 27:
  159. CleanUp();
  160. break;
  161. }
  162. glutPostRedisplay();
  163. }
  164. static void
  165. CheckExtensions(void)
  166. {
  167. const char *req[] = {
  168. "GL_EXT_framebuffer_object",
  169. "GL_ARB_draw_buffers",
  170. "GL_EXT_draw_buffers2"
  171. };
  172. const char *version = (const char *) glGetString(GL_VERSION);
  173. GLint numBuf;
  174. GLint i;
  175. for (i = 0; i < 3; i++) {
  176. if (!glutExtensionSupported(req[i])) {
  177. printf("Sorry, %s extension is required!\n", req[i]);
  178. exit(1);
  179. }
  180. }
  181. if (version[0] != '2') {
  182. printf("Sorry, OpenGL 2.0 is required!\n");
  183. exit(1);
  184. }
  185. glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &numBuf);
  186. printf("GL_MAX_DRAW_BUFFERS_ARB = %d\n", numBuf);
  187. if (numBuf < 2) {
  188. printf("Sorry, GL_MAX_DRAW_BUFFERS_ARB needs to be >= 2\n");
  189. exit(1);
  190. }
  191. printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
  192. }
  193. static void
  194. SetupRenderbuffers(void)
  195. {
  196. glGenFramebuffersEXT(1, &FBobject);
  197. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
  198. glGenRenderbuffersEXT(3, RBobjects);
  199. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
  200. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
  201. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
  202. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
  203. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
  204. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
  205. Width, Height);
  206. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
  207. GL_RENDERBUFFER_EXT, RBobjects[0]);
  208. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
  209. GL_RENDERBUFFER_EXT, RBobjects[1]);
  210. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
  211. GL_RENDERBUFFER_EXT, RBobjects[2]);
  212. CheckError(__LINE__);
  213. }
  214. static GLuint
  215. LoadAndCompileShader(GLenum target, const char *text)
  216. {
  217. GLint stat;
  218. GLuint shader = glCreateShader_func(target);
  219. glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
  220. glCompileShader_func(shader);
  221. glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
  222. if (!stat) {
  223. GLchar log[1000];
  224. GLsizei len;
  225. glGetShaderInfoLog_func(shader, 1000, &len, log);
  226. fprintf(stderr, "drawbuffers: problem compiling shader:\n%s\n", log);
  227. exit(1);
  228. }
  229. return shader;
  230. }
  231. static void
  232. CheckLink(GLuint prog)
  233. {
  234. GLint stat;
  235. glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
  236. if (!stat) {
  237. GLchar log[1000];
  238. GLsizei len;
  239. glGetProgramInfoLog_func(prog, 1000, &len, log);
  240. fprintf(stderr, "drawbuffers: shader link error:\n%s\n", log);
  241. }
  242. }
  243. static void
  244. SetupShaders(void)
  245. {
  246. /* emit same color to both draw buffers */
  247. static const char *fragShaderText =
  248. "void main() {\n"
  249. " gl_FragData[0] = gl_Color; \n"
  250. " gl_FragData[1] = gl_Color; \n"
  251. "}\n";
  252. GLuint fragShader;
  253. fragShader = LoadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
  254. Program = glCreateProgram_func();
  255. glAttachShader_func(Program, fragShader);
  256. glLinkProgram_func(Program);
  257. CheckLink(Program);
  258. glUseProgram_func(Program);
  259. }
  260. static void
  261. SetupLighting(void)
  262. {
  263. static const GLfloat ambient[4] = { 0.0, 0.0, 0.0, 0.0 };
  264. static const GLfloat diffuse[4] = { 1.0, 1.0, 1.0, 0.75 };
  265. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
  266. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
  267. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
  268. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
  269. glEnable(GL_LIGHT0);
  270. glEnable(GL_LIGHTING);
  271. }
  272. static void
  273. Init(void)
  274. {
  275. CheckExtensions();
  276. GetExtensionFuncs();
  277. SetupRenderbuffers();
  278. SetupShaders();
  279. SetupLighting();
  280. glEnable(GL_DEPTH_TEST);
  281. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  282. glEnableIndexedEXT(GL_BLEND, 1);
  283. }
  284. int
  285. main(int argc, char *argv[])
  286. {
  287. glutInit(&argc, argv);
  288. glutInitWindowPosition(0, 0);
  289. glutInitWindowSize(Width, Height);
  290. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  291. Win = glutCreateWindow(argv[0]);
  292. glewInit();
  293. glutIdleFunc(Anim ? Idle : NULL);
  294. glutReshapeFunc(Reshape);
  295. glutKeyboardFunc(Key);
  296. glutDisplayFunc(Display);
  297. Init();
  298. glutMainLoop();
  299. return 0;
  300. }