1 /* 2 Copyright (c) 2019 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.graphics.deferred; 29 30 import std.stdio; 31 import std.conv; 32 33 import dlib.core.memory; 34 import dlib.math.vector; 35 import dlib.math.matrix; 36 import dlib.math.transformation; 37 import dlib.image.color; 38 39 import dagon.core.libs; 40 import dagon.core.ownership; 41 import dagon.core.interfaces; 42 import dagon.graphics.rc; 43 import dagon.graphics.view; 44 import dagon.graphics.gbuffer; 45 import dagon.graphics.framebuffer; 46 import dagon.graphics.shadow; 47 import dagon.graphics.light; 48 import dagon.graphics.screensurface; 49 import dagon.graphics.shapes; 50 import dagon.graphics.shaders.environmentpass; 51 import dagon.graphics.shaders.arealight; 52 import dagon.graphics.shaders.sunlight; 53 import dagon.resource.scene; 54 55 class DeferredEnvironmentPass: Owner 56 { 57 EnvironmentPassShader shader; 58 GBuffer gbuffer; 59 ScreenSurface surface; 60 61 this(GBuffer gbuffer, Owner o) 62 { 63 super(o); 64 this.shader = New!EnvironmentPassShader(gbuffer, this); 65 this.gbuffer = gbuffer; 66 this.surface = New!ScreenSurface(this); 67 } 68 69 void render(RenderingContext* rc2d, RenderingContext* rc3d) 70 { 71 glEnablei(GL_BLEND, 0); 72 glEnablei(GL_BLEND, 1); 73 glBlendFunci(0, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 74 glBlendFunci(1, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 75 76 shader.gbuffer = gbuffer; 77 shader.bind(rc2d, rc3d); 78 surface.render(rc2d); 79 shader.unbind(rc2d, rc3d); 80 81 glDisablei(GL_BLEND, 0); 82 glDisablei(GL_BLEND, 1); 83 } 84 } 85 86 class DeferredLightPass: Owner 87 { 88 AreaLightShader areaLightShader; 89 SunLightShader sunLightShader; 90 GBuffer gbuffer; 91 ShapeSphere lightVolume; 92 ScreenSurface surface; 93 94 this(GBuffer gbuffer, Owner o) 95 { 96 super(o); 97 this.areaLightShader = New!AreaLightShader(gbuffer, this); 98 this.sunLightShader = New!SunLightShader(gbuffer, this); 99 this.gbuffer = gbuffer; 100 this.lightVolume = New!ShapeSphere(1.0f, 8, 4, false, this); 101 this.surface = New!ScreenSurface(this); 102 } 103 104 void render(Scene scene, RenderingContext* rc2d, RenderingContext* rc3d) 105 { 106 areaLightShader.gbuffer = gbuffer; 107 sunLightShader.gbuffer = gbuffer; 108 109 glDisable(GL_DEPTH_TEST); 110 glDepthMask(GL_FALSE); 111 112 glEnable(GL_CULL_FACE); 113 glCullFace(GL_FRONT); 114 115 glEnablei(GL_BLEND, 0); 116 glEnablei(GL_BLEND, 1); 117 glEnablei(GL_BLEND, 4); 118 glBlendFunci(0, GL_ONE, GL_ONE); 119 glBlendFunci(1, GL_ONE, GL_ONE); 120 121 auto rc3dLocal = *rc3d; 122 rc3dLocal.rebindShaderProgram = false; 123 124 areaLightShader.bindProgram(); 125 foreach(light; scene.lightManager.lightSources.data) 126 if (light.type == LightType.AreaSphere || 127 light.type == LightType.AreaTube || 128 light.type == LightType.Spot) 129 { 130 areaLightShader.light = light; 131 areaLightShader.bind(rc2d, &rc3dLocal); 132 lightVolume.render(&rc3dLocal); 133 areaLightShader.unbind(rc2d, &rc3dLocal); 134 } 135 areaLightShader.unbindProgram(); 136 137 glCullFace(GL_BACK); 138 glDisable(GL_CULL_FACE); 139 140 sunLightShader.bindProgram(); 141 foreach(light; scene.lightManager.lightSources.data) 142 if (light.type == LightType.Sun) 143 { 144 sunLightShader.light = light; 145 sunLightShader.shadowMap = cast(CascadedShadowMap)light.shadowMap; 146 sunLightShader.bind(rc2d, &rc3dLocal); 147 surface.render(rc2d); 148 sunLightShader.unbind(rc2d, &rc3dLocal); 149 } 150 sunLightShader.unbindProgram(); 151 152 glDisablei(GL_BLEND, 0); 153 glDisablei(GL_BLEND, 1); 154 155 glDepthMask(GL_TRUE); 156 glEnable(GL_DEPTH_TEST); 157 } 158 }