| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- module three.renderer;
- import three.common;
- import three.scene;
- import three.camera;
- import three.renderTarget;
- import three.viewport;
- enum forwardRendererVertexShaderSource = "
- #version 420 core
- layout(location = 0) in vec3 in_position;
- layout(location = 1) in vec3 in_normal;
- layout(location = 2) in vec2 in_texcoord;
- layout(location = 3) in vec4 in_color;
- out vec4 v_color;
- out gl_PerVertex
- {
- vec4 gl_Position;
- };
- void main()
- {
- gl_Position = vec4(0.005 * in_position.x, 0.005 * in_position.y, 0.005* in_position.z, 1.0);
- v_color = in_color;
- }
- ";
- enum forwardRendererFragmentShaderSource = "
- #version 420 core
- in vec4 v_color;
- out vec4 FragColor;
- void main()
- {
- FragColor = v_color;
- }
- ";
- struct GBuffer {
- uint width;
- uint height;
- GLuint textureDepth;
- GLuint textureNormal;
- GLuint textureColor;
- GLuint textureDepthStencil;
- GLuint fbo;
- }
- void construct(out GBuffer gBuffer, uint width, uint height) nothrow {
- gBuffer.width = width;
- gBuffer.height = height;
-
- glCheck!glGenTextures(1, &gBuffer.textureDepth);
- glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureDepth);
- 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_DEPTH_COMPONENT32F, width, height);
- glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, null);
- glCheck!glBindTexture(GL_TEXTURE_2D, 0);
-
- glCheck!glGenTextures(1, &gBuffer.textureNormal);
- glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.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!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
- glCheck!glBindTexture(GL_TEXTURE_2D, 0);
-
- glCheck!glGenTextures(1, &gBuffer.textureColor);
- glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureColor);
- 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!glBindTexture(GL_TEXTURE_2D, 0);
-
- glCheck!glGenTextures(1, &gBuffer.textureDepthStencil);
- glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureDepthStencil);
- 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!glBindTexture(GL_TEXTURE_2D, 0);
-
- glCheck!glGenFramebuffers(1, &gBuffer.fbo);
- glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gBuffer.fbo);
-
- glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, gBuffer.textureDepth, 0);
- glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 1, GL_TEXTURE_2D, gBuffer.textureNormal, 0);
- glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 2, GL_TEXTURE_2D, gBuffer.textureColor, 0);
- glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, gBuffer.textureDepthStencil, 0);
-
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- }
- void destruct(ref GBuffer gBuffer) nothrow {
- glCheck!glDeleteFramebuffers(1, &gBuffer.fbo);
- glCheck!glDeleteTextures(1, &gBuffer.textureDepthStencil);
- glCheck!glDeleteTextures(1, &gBuffer.textureColor);
- glCheck!glDeleteTextures(1, &gBuffer.textureNormal);
- glCheck!glDeleteTextures(1, &gBuffer.textureDepth);
- gBuffer = GBuffer.init;
- }
- struct Pipeline {
- GLuint pipeline;
- GLuint vertexShaderGeometryPass;
- GLuint fragmentShaderGeometryPass;
- }
- void construct(out Pipeline pipeline) nothrow {
- glCheck!glGenProgramPipelines(1, &pipeline.pipeline);
- import std.string : toStringz;
- auto szVertexSource = [forwardRendererVertexShaderSource.toStringz()];
- pipeline.vertexShaderGeometryPass = glCheck!glCreateShaderProgramv(GL_VERTEX_SHADER, 1, szVertexSource.ptr);
- auto szFragmentSource = [forwardRendererFragmentShaderSource.toStringz()];
- pipeline.fragmentShaderGeometryPass = glCheck!glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, szFragmentSource.ptr);
- glCheck!glUseProgramStages(pipeline.pipeline, GL_VERTEX_SHADER_BIT, pipeline.vertexShaderGeometryPass);
- glCheck!glUseProgramStages(pipeline.pipeline, GL_FRAGMENT_SHADER_BIT, pipeline.fragmentShaderGeometryPass);
- glCheck!glActiveShaderProgram(pipeline.pipeline, pipeline.vertexShaderGeometryPass);
- glCheck!glActiveShaderProgram(pipeline.pipeline, pipeline.fragmentShaderGeometryPass);
- glCheck!glValidateProgramPipeline(pipeline.pipeline);
- GLint status;
- glCheck!glGetProgramPipelineiv(pipeline.pipeline, GL_VALIDATE_STATUS, &status);
- //TODO: add error handling
- assert(status != 0);
- }
- void destruct(ref Pipeline pipeline) nothrow {
- glDeleteProgramPipelines(1, &pipeline.pipeline);
- pipeline = Pipeline.init;
- }
- struct OpenGlTiledDeferredRenderer {
- GBuffer gBuffer;
- Pipeline pipeline;
- }
- void construct(out OpenGlTiledDeferredRenderer deferredRenderer, uint width, uint height) nothrow {
- deferredRenderer.gBuffer.construct(width, height);
- deferredRenderer.pipeline.construct();
- }
- void destruct(ref OpenGlTiledDeferredRenderer deferredRenderer) nothrow {
- deferredRenderer.pipeline.destruct();
- deferredRenderer.gBuffer.destruct();
- deferredRenderer = OpenGlTiledDeferredRenderer.init;
- }
- // draw the scene supersampled with renderer's with+height onto renderTarget at position+size of viewport
- void renderOneFrame(ref OpenGlTiledDeferredRenderer renderer, ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) {
- // 1. Render the (opaque) geometry into the G-Buffers.
- // 2. Construct a screen space grid, covering the frame buffer, with some fixed tile
- // size, t = (x, y), e.g. 32 × 32 pixels.
- // 3. For each light: find the screen space extents of the light volume and append the
- // light ID to each affected grid cell.
- // 4. For each fragment in the frame buffer, with location f = (x, y).
- // (a) sample the G-Buffers at f.
- // (b) accumulate light contributions from all lights in tile at ⌊f /t⌋
- // (c) output total light contributions to frame buffer at f
- with(renderer.gBuffer) glCheck!glViewport(0, 0, width, height);
-
- //enable depth mask _before_ glClear ing the depth buffer!
- glCheck!glDepthMask(GL_TRUE); scope(exit) glCheck!glDepthMask(GL_FALSE);
- glCheck!glEnable(GL_DEPTH_TEST); scope(exit) glCheck!glDisable(GL_DEPTH_TEST);
- glCheck!glDepthFunc(GL_LEQUAL);
-
- //bind gBuffer
- // glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderer.gBuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- // glCheck!glDrawBuffer(GL_COLOR_ATTACHMENT0 + 0);
- // glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- // GLenum[] drawBuffers = [GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2];
- // glCheck!glDrawBuffers(drawBuffers.length, drawBuffers.ptr);
- // glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
- //bind pipeline
- glCheck!glBindProgramPipeline(renderer.pipeline.pipeline); scope(exit) glCheck!glBindProgramPipeline(0);
-
- {// Draw Geometry
- scope(exit) glCheck!glBindVertexArray(0);
- scope(exit) glCheck!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // TODO: GL_ELEMENT_ARRAY_BUFFER should be vao state, but bugs might make this necessary
-
- for(size_t meshIdx = 0; meshIdx < scene.mesh.cnt; ++meshIdx) {
- glCheck!glBindVertexArray(scene.mesh.vao[meshIdx]);
-
- 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
- glCheck!glDrawElements(GL_TRIANGLES, scene.mesh.cntIndices[meshIdx], GL_UNSIGNED_INT, null);
- }
- }
- }
|