1 /*
2 Copyright (c) 2018 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.gbuffer;
44 import dagon.graphics.framebuffer;
45 import dagon.graphics.shadow;
46 import dagon.graphics.light;
47 import dagon.graphics.screensurface;
48 import dagon.graphics.shapes;
49 import dagon.graphics.shaders.environmentpass;
50 import dagon.graphics.shaders.lightpass;
51 import dagon.resource.scene;
52 
53 class DeferredEnvironmentPass: Owner
54 {
55     EnvironmentPassShader shader;
56     GBuffer gbuffer;
57     CascadedShadowMap shadowMap;
58     ScreenSurface surface;
59 
60     this(GBuffer gbuffer, /*Framebuffer sceneFramebuffer,*/ CascadedShadowMap shadowMap, Owner o)
61     {
62         super(o);
63         this.shader = New!EnvironmentPassShader(gbuffer, /*sceneFramebuffer,*/ shadowMap, this);
64         this.gbuffer = gbuffer;
65         this.shadowMap = shadowMap;
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     LightPassShader shader;
89     GBuffer gbuffer;
90     ShapeSphere lightVolume;
91 
92     this(GBuffer gbuffer, Owner o)
93     {
94         super(o);
95         this.shader = New!LightPassShader(gbuffer, this);
96         this.gbuffer = gbuffer;
97         this.lightVolume = New!ShapeSphere(1.0f, 8, 4, false, this);
98     }
99 
100     void render(Scene scene, RenderingContext* rc2d, RenderingContext* rc3d)
101     {
102         shader.gbuffer = gbuffer;
103         
104         glDisable(GL_DEPTH_TEST);
105         glDepthMask(GL_FALSE);
106 
107         glEnable(GL_CULL_FACE);
108         glCullFace(GL_FRONT);
109 
110         glEnablei(GL_BLEND, 0);
111         glEnablei(GL_BLEND, 1);
112         glEnablei(GL_BLEND, 4);
113         glBlendFunci(0, GL_ONE, GL_ONE);
114         glBlendFunci(1, GL_ONE, GL_ONE);
115 
116         // TODO: don't rebind the shader each time,
117         // use special method to update light data
118         foreach(light; scene.lightManager.lightSources.data)
119         {
120             shader.light = light;
121             shader.bind(rc2d, rc3d);
122             lightVolume.render(rc3d);
123             shader.unbind(rc2d, rc3d);
124         }
125 
126         glDisablei(GL_BLEND, 0);
127         glDisablei(GL_BLEND, 1);
128 
129         glCullFace(GL_BACK);
130         glDisable(GL_CULL_FACE);
131 
132         glDepthMask(GL_TRUE);
133         glEnable(GL_DEPTH_TEST);
134     }
135 }