1
1

renderer.d 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. import three.mesh;
  8. import std.string : toStringz;
  9. import std.exception : collectException;
  10. import std.experimental.logger;
  11. import three.gl.buffer;
  12. import three.gl.draw;
  13. import three.gl.sync;
  14. import three.gl.util;
  15. enum maxVertices = 1024;
  16. enum maxIndices = 1024;
  17. enum maxPerInstanceParams = 1024;
  18. enum maxIndirectCommands = 1024;
  19. enum bufferCount = 3; //tripple buffering
  20. enum kOneSecondInNanoSeconds = GLuint64(1000000000);
  21. struct GBuffer {
  22. uint width;
  23. uint height;
  24. GLuint texturePosition;
  25. GLuint textureNormal;
  26. GLuint textureColor;
  27. GLuint textureDepthStencil;
  28. GLuint fbo;
  29. void construct(uint width, uint height) nothrow {
  30. this.width = width;
  31. this.height = height;
  32. glCheck!glGenTextures(1, &this.texturePosition);
  33. glCheck!glBindTexture(GL_TEXTURE_2D, this.texturePosition);
  34. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, width, height);
  35. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, null);
  36. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  37. glCheck!glGenTextures(1, &this.textureNormal);
  38. glCheck!glBindTexture(GL_TEXTURE_2D, this.textureNormal);
  39. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB10_A2, width, height);
  40. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
  41. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  42. glCheck!glGenTextures(1, &this.textureColor);
  43. glCheck!glBindTexture(GL_TEXTURE_2D, this.textureColor);
  44. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
  45. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
  46. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  47. glCheck!glGenTextures(1, &this.textureDepthStencil);
  48. glCheck!glBindTexture(GL_TEXTURE_2D, this.textureDepthStencil);
  49. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, width, height);
  50. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, null);
  51. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  52. glCheck!glGenFramebuffers(1, &this.fbo);
  53. glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this.fbo);
  54. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, this.texturePosition, 0);
  55. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 1, GL_TEXTURE_2D, this.textureNormal, 0);
  56. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 2, GL_TEXTURE_2D, this.textureColor, 0);
  57. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, this.textureDepthStencil, 0);
  58. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  59. }
  60. void destruct() nothrow {
  61. glCheck!glDeleteFramebuffers(1, &this.fbo);
  62. glCheck!glDeleteTextures(1, &this.textureColor);
  63. glCheck!glDeleteTextures(1, &this.textureNormal);
  64. glCheck!glDeleteTextures(1, &this.texturePosition);
  65. }
  66. }
  67. //======================================================================================================================
  68. //
  69. //======================================================================================================================
  70. struct Renderer {
  71. GBuffer gbuffer;
  72. GlArrayBuffer!VertexData vertexBuffer; // vertex data for all meshes
  73. GlElementArrayBuffer!IndexData indexBuffer; //index data for all meshes
  74. GlShaderStorageBuffer!GlDrawParameter perInstanceParamBuffer; // is filled with draw parameters for each instance each frame. shall be accessed as a ringbuffer
  75. GlDispatchIndirectBuffer!GlDrawElementsIndirectCommand dispatchIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
  76. GlSyncManager syncManager;
  77. void construct(uint width, uint height) {
  78. GLbitfield createFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;//TODO: ?? | GL_MAP_DYNAMIC_STORAGE_BIT;
  79. GLbitfield mapFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
  80. this.gbuffer.construct(width, height);
  81. this.vertexBuffer.construct(bufferCount * maxVertices, createFlags, mapFlags);
  82. this.indexBuffer.construct(bufferCount * maxIndices, createFlags, mapFlags);
  83. this.perInstanceParamBuffer.construct(bufferCount * maxPerInstanceParams, createFlags, mapFlags);
  84. this.dispatchIndirectCommandBuffer.construct(bufferCount * maxIndirectCommands, createFlags, mapFlags);
  85. this.syncManager.construct();
  86. glCheck!glEnableVertexAttribArray(0);
  87. glCheck!glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)0 );
  88. glCheck!glEnableVertexAttribArray(1);
  89. glCheck!glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)3 );
  90. glCheck!glEnableVertexAttribArray(2);
  91. glCheck!glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)6 );
  92. glCheck!glEnableVertexAttribArray(3);
  93. glCheck!glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)10 );
  94. }
  95. void destruct() {
  96. this.syncManager.destruct();
  97. this.dispatchIndirectCommandBuffer.destruct();
  98. this.perInstanceParamBuffer.destruct();
  99. this.indexBuffer.destruct();
  100. this.vertexBuffer.destruct();
  101. this.gbuffer.destruct();
  102. }
  103. // void uploadModelData(GlArrayBuffer!VertexData vertexBuffer, GlElementArrayBuffer!IndexData indexBuffer, ModelData modelData) {
  104. // //TODO: wait for buffer range
  105. // //mBufferLockManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
  106. //
  107. // // TODO: check if buffers are bound. they should always be bound here!
  108. //
  109. // // we need to store all models in one giant vbo to use glMultiDrawElementsIndirect.
  110. // // TODO: implement triple buffering. -> use vertexBuffer and indexBuffer as giant ring buffers
  111. // GLuint vertexBufferOffset = 0;
  112. // GLuint indexBufferOffset = 0;
  113. //
  114. // foreach(meshData; modelData.meshData) {
  115. // import std.c.string: memcpy;
  116. // //upload vertex data
  117. // assert(this.vertexBuffer.length >= meshData.vertexData.length);
  118. // memcpy(this.vertexBuffer.data + vertexBufferOffset, meshData.vertexData.ptr, meshData.vertexData.length * VertexData.sizeof);
  119. // vertexBufferOffset += meshData.vertexData.length * VertexData.sizeof;
  120. // //upload index data
  121. // assert(this.indexBuffer.length >= meshData.indexData.length);
  122. // memcpy(this.indexBuffer.data + indexBufferOffset, meshData.indexData.ptr, meshData.indexData.length * IndexData.sizeof);
  123. // indexBufferOffset += meshData.indexData.length * IndexData.sizeof;
  124. // }
  125. // }
  126. void renderOneFrame(ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) {
  127. // wait until GPU has finished rendereing from our desired buffer destination
  128. //TODO: this.syncManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
  129. /*
  130. foreach(renderTarget) //framebuffer
  131. foreach(pass)
  132. foreach(material) //shaders
  133. foreach(materialInstance) //textures
  134. foreach(vertexFormat) //vertex buffers
  135. foreach(object) {
  136. write uniform data;
  137. glDrawElementsBaseVertex
  138. }
  139. */
  140. GLsizei meshCount = 0;
  141. glCheck!glViewport(0, 0, this.gbuffer.width, this.gbuffer.height);
  142. // enable depth mask _before_ glClear ing the depth buffer!
  143. glCheck!glDepthMask(GL_TRUE); scope(exit) glCheck!glDepthMask(GL_FALSE);
  144. glCheck!glEnable(GL_DEPTH_TEST); scope(exit) glCheck!glDisable(GL_DEPTH_TEST);
  145. glCheck!glDepthFunc(GL_LEQUAL);
  146. // write draw parameters
  147. // write draw commmands
  148. // draw //TODO: pass offset (cast to ptr) into command buffer instead of null
  149. this.vertexBuffer.bind();
  150. this.indexBuffer.bind();
  151. this.perInstanceParamBuffer.bind();
  152. this.dispatchIndirectCommandBuffer.bind();
  153. glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), null, meshCount, 0);
  154. //TODO: this.syncManager.LockRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
  155. }
  156. debug {
  157. void blitGBufferToScreen() {
  158. }
  159. }
  160. }