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 }