|
@@ -1,9 +1,7 @@
|
|
|
-module three.renderer;
|
|
|
|
|
|
|
+module three.gl.renderer;
|
|
|
|
|
|
|
|
-import three.common;
|
|
|
|
|
import three.scene;
|
|
import three.scene;
|
|
|
import three.camera;
|
|
import three.camera;
|
|
|
-import three.renderTarget;
|
|
|
|
|
import three.viewport;
|
|
import three.viewport;
|
|
|
import three.mesh;
|
|
import three.mesh;
|
|
|
|
|
|
|
@@ -16,11 +14,12 @@ import three.gl.buffer;
|
|
|
import three.gl.draw;
|
|
import three.gl.draw;
|
|
|
import three.gl.sync;
|
|
import three.gl.sync;
|
|
|
import three.gl.util;
|
|
import three.gl.util;
|
|
|
|
|
+public import three.gl.renderTarget;
|
|
|
|
|
|
|
|
-enum maxVertices = 1024;
|
|
|
|
|
-enum maxIndices = 1024;
|
|
|
|
|
-enum maxPerInstanceParams = 1024;
|
|
|
|
|
-enum maxIndirectCommands = 1024;
|
|
|
|
|
|
|
+enum maxVertices = 1 * 1024 * 1024;
|
|
|
|
|
+enum maxIndices = 1 * 1024 * 1024;
|
|
|
|
|
+enum maxPerInstanceParams = 1 * 1024 * 1024;
|
|
|
|
|
+enum maxIndirectCommands = 1 * 1024 * 1024;
|
|
|
enum bufferCount = 3; //tripple buffering
|
|
enum bufferCount = 3; //tripple buffering
|
|
|
enum kOneSecondInNanoSeconds = GLuint64(1000000000);
|
|
enum kOneSecondInNanoSeconds = GLuint64(1000000000);
|
|
|
|
|
|
|
@@ -38,34 +37,43 @@ struct GBuffer {
|
|
|
GLuint textureColor;
|
|
GLuint textureColor;
|
|
|
GLuint textureDepthStencil;
|
|
GLuint textureDepthStencil;
|
|
|
GLuint fbo;
|
|
GLuint fbo;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
void construct(uint width, uint height) nothrow {
|
|
void construct(uint width, uint height) nothrow {
|
|
|
this.width = width;
|
|
this.width = width;
|
|
|
this.height = height;
|
|
this.height = height;
|
|
|
glCheck!glGenTextures(1, &this.texturePosition);
|
|
glCheck!glGenTextures(1, &this.texturePosition);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.texturePosition);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.texturePosition);
|
|
|
|
|
+ glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
|
+ glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
+// glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
|
+// glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
|
+// glCheck!glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
|
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, width, height);
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, width, height);
|
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, null);
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, null);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
glCheck!glGenTextures(1, &this.textureNormal);
|
|
glCheck!glGenTextures(1, &this.textureNormal);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.textureNormal);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.textureNormal);
|
|
|
|
|
+ glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
+ glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
+// glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
|
+// glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB10_A2, width, height);
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB10_A2, width, height);
|
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
glCheck!glGenTextures(1, &this.textureColor);
|
|
glCheck!glGenTextures(1, &this.textureColor);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.textureColor);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.textureColor);
|
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
|
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
glCheck!glGenTextures(1, &this.textureDepthStencil);
|
|
glCheck!glGenTextures(1, &this.textureDepthStencil);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.textureDepthStencil);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, this.textureDepthStencil);
|
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, width, height);
|
|
glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, width, height);
|
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, null);
|
|
glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, null);
|
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
glCheck!glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
glCheck!glGenFramebuffers(1, &this.fbo);
|
|
glCheck!glGenFramebuffers(1, &this.fbo);
|
|
|
glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this.fbo);
|
|
glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this.fbo);
|
|
|
glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, this.texturePosition, 0);
|
|
glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, this.texturePosition, 0);
|
|
@@ -94,7 +102,7 @@ struct ShaderPipeline {
|
|
|
GLuint pipeline;
|
|
GLuint pipeline;
|
|
|
GLuint vertexShaderGeometryPass;
|
|
GLuint vertexShaderGeometryPass;
|
|
|
GLuint fragmentShaderGeometryPass;
|
|
GLuint fragmentShaderGeometryPass;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
void construct(string vertexShaderSource, string fragmentShaderSource) nothrow {
|
|
void construct(string vertexShaderSource, string fragmentShaderSource) nothrow {
|
|
|
glCheck!glGenProgramPipelines(1, &this.pipeline);
|
|
glCheck!glGenProgramPipelines(1, &this.pipeline);
|
|
|
|
|
|
|
@@ -127,7 +135,7 @@ struct ShaderPipeline {
|
|
|
//TODO: add error handling
|
|
//TODO: add error handling
|
|
|
assert(status != 0);
|
|
assert(status != 0);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
void destruct() nothrow {
|
|
void destruct() nothrow {
|
|
|
glDeleteProgramPipelines(1, &this.pipeline);
|
|
glDeleteProgramPipelines(1, &this.pipeline);
|
|
|
}
|
|
}
|
|
@@ -202,11 +210,11 @@ struct Renderer {
|
|
|
GlShaderStorageBuffer!GlDrawParameter perInstanceParamBuffer; // is filled with draw parameters for each instance each frame. shall be accessed as a ringbuffer
|
|
GlShaderStorageBuffer!GlDrawParameter perInstanceParamBuffer; // is filled with draw parameters for each instance each frame. shall be accessed as a ringbuffer
|
|
|
GlDispatchIndirectBuffer!GlDrawElementsIndirectCommand dispatchIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
|
|
GlDispatchIndirectBuffer!GlDrawElementsIndirectCommand dispatchIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
|
|
|
GlSyncManager syncManager;
|
|
GlSyncManager syncManager;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
void construct(uint width, uint height) {
|
|
void construct(uint width, uint height) {
|
|
|
GLbitfield createFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;//TODO: ?? | GL_MAP_DYNAMIC_STORAGE_BIT;
|
|
GLbitfield createFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;//TODO: ?? | GL_MAP_DYNAMIC_STORAGE_BIT;
|
|
|
GLbitfield mapFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
|
|
GLbitfield mapFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
this.gbuffer.construct(width, height);
|
|
this.gbuffer.construct(width, height);
|
|
|
this.shaderPipeline.construct(vertexShaderSource, fragmentShaderSource);
|
|
this.shaderPipeline.construct(vertexShaderSource, fragmentShaderSource);
|
|
|
this.vertexBuffer.construct(bufferCount * maxVertices, createFlags, mapFlags);
|
|
this.vertexBuffer.construct(bufferCount * maxVertices, createFlags, mapFlags);
|
|
@@ -214,7 +222,7 @@ struct Renderer {
|
|
|
this.perInstanceParamBuffer.construct(bufferCount * maxPerInstanceParams, createFlags, mapFlags);
|
|
this.perInstanceParamBuffer.construct(bufferCount * maxPerInstanceParams, createFlags, mapFlags);
|
|
|
this.dispatchIndirectCommandBuffer.construct(bufferCount * maxIndirectCommands, createFlags, mapFlags);
|
|
this.dispatchIndirectCommandBuffer.construct(bufferCount * maxIndirectCommands, createFlags, mapFlags);
|
|
|
this.syncManager.construct();
|
|
this.syncManager.construct();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
glCheck!glEnableVertexAttribArray(0);
|
|
glCheck!glEnableVertexAttribArray(0);
|
|
|
glCheck!glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)0 );
|
|
glCheck!glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)0 );
|
|
|
glCheck!glEnableVertexAttribArray(1);
|
|
glCheck!glEnableVertexAttribArray(1);
|
|
@@ -224,7 +232,7 @@ struct Renderer {
|
|
|
glCheck!glEnableVertexAttribArray(3);
|
|
glCheck!glEnableVertexAttribArray(3);
|
|
|
glCheck!glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)10 );
|
|
glCheck!glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)10 );
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
void destruct() {
|
|
void destruct() {
|
|
|
this.syncManager.destruct();
|
|
this.syncManager.destruct();
|
|
|
this.dispatchIndirectCommandBuffer.destruct();
|
|
this.dispatchIndirectCommandBuffer.destruct();
|
|
@@ -234,37 +242,42 @@ struct Renderer {
|
|
|
this.shaderPipeline.destruct();
|
|
this.shaderPipeline.destruct();
|
|
|
this.gbuffer.destruct();
|
|
this.gbuffer.destruct();
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-// void uploadModelData(GlArrayBuffer!VertexData vertexBuffer, GlElementArrayBuffer!IndexData indexBuffer, ModelData modelData) {
|
|
|
|
|
-// //TODO: wait for buffer range
|
|
|
|
|
-// //mBufferLockManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
|
|
|
|
|
-//
|
|
|
|
|
-// // TODO: check if buffers are bound. they should always be bound here!
|
|
|
|
|
-//
|
|
|
|
|
-// // we need to store all models in one giant vbo to use glMultiDrawElementsIndirect.
|
|
|
|
|
-// // TODO: implement triple buffering. -> use vertexBuffer and indexBuffer as giant ring buffers
|
|
|
|
|
-// GLuint vertexBufferOffset = 0;
|
|
|
|
|
-// GLuint indexBufferOffset = 0;
|
|
|
|
|
-//
|
|
|
|
|
-// foreach(meshData; modelData.meshData) {
|
|
|
|
|
-// import std.c.string: memcpy;
|
|
|
|
|
-// //upload vertex data
|
|
|
|
|
-// assert(this.vertexBuffer.length >= meshData.vertexData.length);
|
|
|
|
|
-// memcpy(this.vertexBuffer.data + vertexBufferOffset, meshData.vertexData.ptr, meshData.vertexData.length * VertexData.sizeof);
|
|
|
|
|
-// vertexBufferOffset += meshData.vertexData.length * VertexData.sizeof;
|
|
|
|
|
-// //upload index data
|
|
|
|
|
-// assert(this.indexBuffer.length >= meshData.indexData.length);
|
|
|
|
|
-// memcpy(this.indexBuffer.data + indexBufferOffset, meshData.indexData.ptr, meshData.indexData.length * IndexData.sizeof);
|
|
|
|
|
-// indexBufferOffset += meshData.indexData.length * IndexData.sizeof;
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
- void renderOneFrame(ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) {
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // void uploadModelData(GlArrayBuffer!VertexData vertexBuffer, GlElementArrayBuffer!IndexData indexBuffer, ModelData modelData) {
|
|
|
|
|
+ // //TODO: wait for buffer range
|
|
|
|
|
+ // //mBufferLockManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
|
|
|
|
|
+ //
|
|
|
|
|
+ // // TODO: check if buffers are bound. they should always be bound here!
|
|
|
|
|
+ //
|
|
|
|
|
+ // // we need to store all models in one giant vbo to use glMultiDrawElementsIndirect.
|
|
|
|
|
+ // // TODO: implement triple buffering. -> use vertexBuffer and indexBuffer as giant ring buffers
|
|
|
|
|
+ // GLuint vertexBufferOffset = 0;
|
|
|
|
|
+ // GLuint indexBufferOffset = 0;
|
|
|
|
|
+ //
|
|
|
|
|
+ // foreach(meshData; modelData.meshData) {
|
|
|
|
|
+ // import std.c.string: memcpy;
|
|
|
|
|
+ // //upload vertex data
|
|
|
|
|
+ // assert(this.vertexBuffer.length >= meshData.vertexData.length);
|
|
|
|
|
+ // memcpy(this.vertexBuffer.data + vertexBufferOffset, meshData.vertexData.ptr, meshData.vertexData.length * VertexData.sizeof);
|
|
|
|
|
+ // vertexBufferOffset += meshData.vertexData.length * VertexData.sizeof;
|
|
|
|
|
+ // //upload index data
|
|
|
|
|
+ // assert(this.indexBuffer.length >= meshData.indexData.length);
|
|
|
|
|
+ // memcpy(this.indexBuffer.data + indexBufferOffset, meshData.indexData.ptr, meshData.indexData.length * IndexData.sizeof);
|
|
|
|
|
+ // indexBufferOffset += meshData.indexData.length * IndexData.sizeof;
|
|
|
|
|
+ // }
|
|
|
|
|
+ // }
|
|
|
|
|
+
|
|
|
|
|
+ void renderOneFrame(ref Scene scene, ref Camera camera, ref GlRenderTarget renderTarget, ref Viewport viewport) nothrow {
|
|
|
|
|
+
|
|
|
|
|
+ glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
+ glCheck!glClearDepth(1.0f);
|
|
|
|
|
+ glCheck!glClearColor(0, 0.3, 0, 1);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
// wait until GPU has finished rendereing from our desired buffer destination
|
|
// wait until GPU has finished rendereing from our desired buffer destination
|
|
|
//TODO: this.syncManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
|
|
//TODO: this.syncManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
foreach(renderTarget) //framebuffer
|
|
foreach(renderTarget) //framebuffer
|
|
|
foreach(pass)
|
|
foreach(pass)
|
|
@@ -291,7 +304,7 @@ struct Renderer {
|
|
|
// write draw commmands
|
|
// write draw commmands
|
|
|
|
|
|
|
|
// draw //TODO: pass offset (cast to ptr) into command buffer instead of null
|
|
// draw //TODO: pass offset (cast to ptr) into command buffer instead of null
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
this.vertexBuffer.bind();
|
|
this.vertexBuffer.bind();
|
|
|
this.indexBuffer.bind();
|
|
this.indexBuffer.bind();
|
|
@@ -299,7 +312,7 @@ struct Renderer {
|
|
|
this.dispatchIndirectCommandBuffer.bind();
|
|
this.dispatchIndirectCommandBuffer.bind();
|
|
|
|
|
|
|
|
glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), null, meshCount, 0);
|
|
glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), null, meshCount, 0);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
//TODO: this.syncManager.LockRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
|
|
//TODO: this.syncManager.LockRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
|
|
|
}
|
|
}
|
|
|
|
|
|