renderer.d 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. module three.renderer;
  2. import three.common;
  3. import three.scene;
  4. import three.camera;
  5. import three.renderTarget;
  6. import three.viewport;
  7. struct GBuffer {
  8. uint width;
  9. uint height;
  10. GLuint textureDepth;
  11. GLuint textureNormal;
  12. GLuint textureColor;
  13. GLuint textureDepthStencil;
  14. GLuint fbo;
  15. }
  16. void construct(out GBuffer gBuffer, uint width, uint height) nothrow {
  17. gBuffer.width = width;
  18. gBuffer.width = height;
  19. glCheck!glGenTextures(1, &gBuffer.textureDepth);
  20. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureDepth);
  21. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  22. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  23. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  24. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  25. // glCheck!glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
  26. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, width, height);
  27. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, null);
  28. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  29. glCheck!glGenTextures(1, &gBuffer.textureNormal);
  30. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureNormal);
  31. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  32. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  33. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  34. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  35. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB10_A2, width, height);
  36. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
  37. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  38. glCheck!glGenTextures(1, &gBuffer.textureColor);
  39. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureColor);
  40. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
  41. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
  42. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  43. glCheck!glGenTextures(1, &gBuffer.textureDepthStencil);
  44. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureDepthStencil);
  45. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, width, height);
  46. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, null);
  47. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  48. glCheck!glGenFramebuffers(1, &gBuffer.fbo);
  49. glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gBuffer.fbo);
  50. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, gBuffer.textureDepth, 0);
  51. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 1, GL_TEXTURE_2D, gBuffer.textureNormal, 0);
  52. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 2, GL_TEXTURE_2D, gBuffer.textureColor, 0);
  53. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, gBuffer.textureDepthStencil, 0);
  54. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  55. }
  56. void destruct(ref GBuffer gBuffer) nothrow {
  57. glCheck!glDeleteFramebuffers(1, &gBuffer.fbo);
  58. glCheck!glDeleteTextures(1, &gBuffer.textureDepthStencil);
  59. glCheck!glDeleteTextures(1, &gBuffer.textureColor);
  60. glCheck!glDeleteTextures(1, &gBuffer.textureNormal);
  61. glCheck!glDeleteTextures(1, &gBuffer.textureDepth);
  62. gBuffer = GBuffer.init;
  63. }
  64. struct Pipeline {
  65. GLuint pipeline;
  66. GLuint vertexShaderGeometryPass;
  67. GLuint fragmentShaderGeometryPass;
  68. }
  69. void construct(out Pipeline pipeline) nothrow {
  70. glGenProgramPipelines(1, &pipeline.pipeline);
  71. }
  72. void destruct(ref Pipeline pipeline) nothrow {
  73. glDeleteProgramPipelines(1, &pipeline.pipeline);
  74. pipeline = Pipeline.init;
  75. }
  76. struct OpenGlTiledDeferredRenderer {
  77. GBuffer gBuffer;
  78. Pipeline pipeline;
  79. }
  80. void construct(out OpenGlTiledDeferredRenderer deferredRenderer, uint width, uint height) nothrow {
  81. deferredRenderer.gBuffer.construct(width, height);
  82. }
  83. void destruct(ref OpenGlTiledDeferredRenderer deferredRenderer) nothrow {
  84. deferredRenderer.gBuffer.destruct();
  85. deferredRenderer = OpenGlTiledDeferredRenderer.init;
  86. }
  87. // draw the scene supersampled with renderer's with+height onto renderTarget at position+size of viewport
  88. void renderOneFrame(ref OpenGlTiledDeferredRenderer renderer, ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) nothrow {
  89. // 1. Render the (opaque) geometry into the G-Buffers.
  90. // 2. Construct a screen space grid, covering the frame buffer, with some fixed tile
  91. // size, t = (x, y), e.g. 32 × 32 pixels.
  92. // 3. For each light: find the screen space extents of the light volume and append the
  93. // light ID to each affected grid cell.
  94. // 4. For each fragment in the frame buffer, with location f = (x, y).
  95. // (a) sample the G-Buffers at f.
  96. // (b) accumulate light contributions from all lights in tile at ⌊f /t⌋
  97. // (c) output total light contributions to frame buffer at f
  98. with(renderer.gBuffer) glCheck!glViewport(0, 0, width, height);
  99. //enable depth mask _before_ glClear ing the depth buffer!
  100. glCheck!glDepthMask(GL_TRUE); scope(exit) glCheck!glDepthMask(GL_FALSE);
  101. glCheck!glEnable(GL_DEPTH_TEST); scope(exit) glCheck!glDisable(GL_DEPTH_TEST);
  102. glCheck!glDepthFunc(GL_LEQUAL);
  103. //bind gBuffer
  104. glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderer.gBuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  105. glCheck!glDrawBuffer(GL_COLOR_ATTACHMENT0 + 0);
  106. glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  107. GLenum[] drawBuffers = [GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2];
  108. glCheck!glDrawBuffers(drawBuffers.length, drawBuffers.ptr);
  109. glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  110. //bind pipeline
  111. glCheck!glBindProgramPipeline(renderer.pipeline.pipeline); scope(exit) glCheck!glBindProgramPipeline(0);
  112. {// Draw Geometry
  113. scope(exit) glCheck!glBindVertexArray(0);
  114. scope(exit) glCheck!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // TODO: GL_ELEMENT_ARRAY_BUFFER should be vao state, but bugs might make this necessary
  115. for(size_t meshIdx = 0; meshIdx < scene.mesh.cnt; ++meshIdx) {
  116. glCheck!glBindVertexArray(scene.mesh.vao[meshIdx]);
  117. glCheck!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene.mesh.vboIndices[meshIdx]); // TODO: GL_ELEMENT_ARRAY_BUFFER should be vao state, but bugs might make this necessary
  118. glCheck!glDrawElements(GL_TRIANGLES, scene.mesh.cntIndices[meshIdx], GL_UNSIGNED_SHORT, null);
  119. }
  120. }
  121. }