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.

geometry.cc 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include <png.h>
  2. #include <EGL/egl.h>
  3. #include <GL/gl.h>
  4. #include <GL/glext.h>
  5. #include <GLES3/gl32.h>
  6. #include <fstream>
  7. #include <iostream>
  8. #include <sstream>
  9. #include <string>
  10. const uint32_t kWidth = 255;
  11. const uint32_t kHeight = 255;
  12. const uint32_t kLayers = 10;
  13. const std::string kVertexShaderPath = "geometry.vert";
  14. const std::string kGeometryShaderPath = "geometry.geom";
  15. const std::string kFragmentShaderPath = "geometry.frag";
  16. const std::string kBlitVertexPath = "blit.vert";
  17. const std::string kBlitFragmentPath = "blit.frag";
  18. EGLDisplay display;
  19. EGLContext context;
  20. GLuint program;
  21. #define ERROR(message) \
  22. std::cerr << message << std::endl; \
  23. std::exit(EXIT_FAILURE)
  24. void InitializeEGL() {
  25. display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  26. eglInitialize(display, nullptr, nullptr);
  27. eglBindAPI(EGL_OPENGL_ES_API);
  28. const EGLint config_attribs[] = {
  29. EGL_SURFACE_TYPE, EGL_DONT_CARE,
  30. EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
  31. EGL_NONE };
  32. EGLConfig egl_config;
  33. EGLint num_configs;
  34. if (!eglChooseConfig(display, config_attribs, &egl_config, 1, &num_configs)) {
  35. ERROR("Unable to choose EGL config");
  36. }
  37. const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
  38. context = eglCreateContext(display, egl_config, EGL_NO_CONTEXT, context_attribs);
  39. if (context == EGL_NO_CONTEXT) {
  40. ERROR("Failed to create GLES context");
  41. }
  42. if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context)) {
  43. ERROR("Failed to make GLES context current");
  44. }
  45. std::cout << glGetString(GL_VERSION) << std::endl;
  46. }
  47. void SetUpLayeredFramebuffer(GLuint layered_texture) {
  48. glBindTexture(GL_TEXTURE_2D_ARRAY, layered_texture);
  49. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  50. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  51. glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kWidth, kHeight, kLayers, 0,
  52. GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
  53. glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
  54. GLuint framebuffer;
  55. glGenFramebuffers(1, &framebuffer);
  56. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
  57. glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, layered_texture, 0);
  58. }
  59. void SetUpBasicFramebuffer() {
  60. GLuint color_buffer;
  61. glGenRenderbuffers(1, &color_buffer);
  62. glBindRenderbuffer(GL_RENDERBUFFER, color_buffer);
  63. glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
  64. GLuint framebuffer;
  65. glGenFramebuffers(1, &framebuffer);
  66. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
  67. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color_buffer);
  68. }
  69. GLuint CompileShader(GLenum type, std::string path) {
  70. std::ifstream fstream(path);
  71. if (!fstream) {
  72. ERROR("Unable to read shader: " << path);
  73. }
  74. std::stringstream buffer;
  75. buffer << fstream.rdbuf();
  76. // TODO(brkho): Read the shader source in more intelligently.
  77. std::string shader_source_tmp = buffer.str();
  78. const char* shader_source = shader_source_tmp.c_str();
  79. GLuint shader = glCreateShader(type);
  80. if (!shader) {
  81. ERROR("Failed to create shader of type: " << type);
  82. }
  83. glShaderSource(shader, 1, &shader_source, nullptr);
  84. glCompileShader(shader);
  85. GLint status;
  86. glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
  87. if (!status) {
  88. GLint log_length;
  89. glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
  90. char shader_log[log_length];
  91. glGetShaderInfoLog(shader, log_length, nullptr, shader_log);
  92. ERROR("Failed to compile shader: " << shader_log);
  93. }
  94. return shader;
  95. }
  96. GLuint CreateProgram() {
  97. GLuint vertex_shader = CompileShader(GL_VERTEX_SHADER, kVertexShaderPath);
  98. GLuint geometry_shader = CompileShader(GL_GEOMETRY_SHADER, kGeometryShaderPath);
  99. GLuint fragment_shader = CompileShader(GL_FRAGMENT_SHADER, kFragmentShaderPath);
  100. GLuint program = glCreateProgram();
  101. if (!program) {
  102. ERROR("Failed to create program");
  103. }
  104. glAttachShader(program, vertex_shader);
  105. glAttachShader(program, geometry_shader);
  106. glAttachShader(program, fragment_shader);
  107. glLinkProgram(program);
  108. GLint status;
  109. glGetProgramiv(program, GL_LINK_STATUS, &status);
  110. if (!status) {
  111. GLint log_length = 0;
  112. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
  113. char program_log[log_length];
  114. glGetProgramInfoLog(program, log_length, nullptr, program_log);
  115. ERROR("Failed to link program: " << program_log);
  116. }
  117. glDetachShader(program, vertex_shader);
  118. glDetachShader(program, geometry_shader);
  119. glDetachShader(program, fragment_shader);
  120. glDeleteShader(vertex_shader);
  121. glDeleteShader(geometry_shader);
  122. glDeleteShader(fragment_shader);
  123. return program;
  124. }
  125. GLuint CreateBlitProgram() {
  126. GLuint vertex_shader = CompileShader(GL_VERTEX_SHADER, kBlitVertexPath);
  127. GLuint fragment_shader = CompileShader(GL_FRAGMENT_SHADER, kBlitFragmentPath);
  128. GLuint program = glCreateProgram();
  129. if (!program) {
  130. ERROR("Failed to create program");
  131. }
  132. glAttachShader(program, vertex_shader);
  133. glAttachShader(program, fragment_shader);
  134. glLinkProgram(program);
  135. GLint status;
  136. glGetProgramiv(program, GL_LINK_STATUS, &status);
  137. if (!status) {
  138. GLint log_length = 0;
  139. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
  140. char program_log[log_length];
  141. glGetProgramInfoLog(program, log_length, nullptr, program_log);
  142. ERROR("Failed to link program: " << program_log);
  143. }
  144. glDetachShader(program, vertex_shader);
  145. glDetachShader(program, fragment_shader);
  146. glDeleteShader(vertex_shader);
  147. glDeleteShader(fragment_shader);
  148. return program;
  149. }
  150. void Draw(GLuint program) {
  151. glViewport(0, 0, kWidth, kHeight);
  152. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  153. glClear(GL_COLOR_BUFFER_BIT);
  154. glUseProgram(program);
  155. glDrawArrays(GL_POINTS, 0, 1);
  156. glFinish();
  157. }
  158. void Blit(GLuint program, GLuint layered_texture) {
  159. glViewport(0, 0, kWidth, kHeight);
  160. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  161. glClear(GL_COLOR_BUFFER_BIT);
  162. glActiveTexture(GL_TEXTURE0);
  163. glBindTexture(GL_TEXTURE_2D_ARRAY, layered_texture);
  164. glUseProgram(program);
  165. glDrawArrays(GL_TRIANGLES, 0, 6);
  166. glFinish();
  167. }
  168. GLubyte* ReadFramebuffer() {
  169. // TODO(brkho): Maybe use a std::array instead?
  170. GLubyte* pixels = static_cast<GLubyte*>(malloc(kWidth * kHeight * 4));
  171. glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  172. return pixels;
  173. }
  174. void WriteImage(GLubyte* pixels) {
  175. FILE *f = fopen("geometry.png", "wb");
  176. png_image image_info = {};
  177. image_info.version = PNG_IMAGE_VERSION;
  178. image_info.width = kWidth;
  179. image_info.height = kHeight;
  180. image_info.format = PNG_FORMAT_RGBA;
  181. if (png_image_write_to_stdio(&image_info, f, 0, pixels, kWidth * 4, nullptr) == 0) {
  182. ERROR("Error writing PNG: " << image_info.message);
  183. }
  184. fclose(f);
  185. }
  186. int main() {
  187. InitializeEGL();
  188. GLuint layered_texture;
  189. glGenTextures(1, &layered_texture);
  190. SetUpLayeredFramebuffer(layered_texture);
  191. GLuint program = CreateProgram();
  192. Draw(program);
  193. SetUpBasicFramebuffer();
  194. GLuint blit_program = CreateBlitProgram();
  195. Blit(blit_program, layered_texture);
  196. GLubyte* pixels = ReadFramebuffer();
  197. WriteImage(pixels);
  198. eglMakeCurrent(display, EGL_NO_SURFACE,EGL_NO_SURFACE, EGL_NO_CONTEXT);
  199. eglDestroyContext(display, context);
  200. eglTerminate(display);
  201. return EXIT_SUCCESS;
  202. }