1 /*
2 Copyright (c) 2019-2020 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.render.shaders.sunlight;
29 
30 import std.stdio;
31 import std.math;
32 
33 import dlib.core.memory;
34 import dlib.core.ownership;
35 import dlib.math.vector;
36 import dlib.math.matrix;
37 import dlib.math.transformation;
38 import dlib.math.interpolation;
39 import dlib.image.color;
40 import dlib.text.str;
41 
42 import dagon.core.bindings;
43 import dagon.graphics.shader;
44 import dagon.graphics.state;
45 import dagon.graphics.csm;
46 
47 class SunLightShader: Shader
48 {
49     String vs, fs;
50 
51     Matrix4x4f defaultShadowMatrix;
52     GLuint defaultShadowTexture;
53 
54     this(Owner owner)
55     {
56         vs = Shader.load("data/__internal/shaders/SunLight/SunLight.vert.glsl");
57         fs = Shader.load("data/__internal/shaders/SunLight/SunLight.frag.glsl");
58 
59         auto myProgram = New!ShaderProgram(vs, fs, this);
60         super(myProgram, owner);
61 
62         defaultShadowMatrix = Matrix4x4f.identity;
63 
64         glGenTextures(1, &defaultShadowTexture);
65         glActiveTexture(GL_TEXTURE0);
66         glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture);
67         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, 1, 1, 3, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null);
68         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
69         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
70         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
71     }
72 
73     ~this()
74     {
75         if (glIsFramebuffer(defaultShadowTexture))
76             glDeleteFramebuffers(1, &defaultShadowTexture);
77 
78         vs.free();
79         fs.free();
80     }
81 
82     override void bindParameters(GraphicsState* state)
83     {
84         setParameter("viewMatrix", state.viewMatrix);
85         setParameter("invViewMatrix", state.invViewMatrix);
86         setParameter("projectionMatrix", state.projectionMatrix);
87         setParameter("invProjectionMatrix", state.invProjectionMatrix);
88         setParameter("resolution", state.resolution);
89         setParameter("zNear", state.zNear);
90         setParameter("zFar", state.zFar);
91 
92         // Environment
93         if (state.environment)
94         {
95             setParameter("fogColor", state.environment.fogColor);
96             setParameter("fogStart", state.environment.fogStart);
97             setParameter("fogEnd", state.environment.fogEnd);
98         }
99         else
100         {
101             setParameter("fogColor", Color4f(0.5f, 0.5f, 0.5f, 1.0f));
102             setParameter("fogStart", 0.0f);
103             setParameter("fogEnd", 1000.0f);
104         }
105 
106         // Light
107         Vector4f lightDirHg;
108         Color4f lightColor;
109         float lightEnergy = 1.0f;
110         int lightScattering = 0;
111         float lightScatteringG = 0.0f;
112         float lightScatteringDensity = 0.0f;
113         int lightScatteringSamples = 1;
114         float lightScatteringMaxRandomStepOffset = 0.0f;
115         bool lightScatteringShadow = false;
116         float lightDiffuse = 1.0f;
117         float lightSpecular = 1.0f;
118         if (state.light)
119         {
120             auto light = state.light;
121             lightDirHg = Vector4f(light.directionAbsolute);
122             lightDirHg.w = 0.0;
123             lightColor = light.color;
124             lightEnergy = light.energy;
125             lightScattering = light.scatteringEnabled;
126             lightScatteringG = 1.0f - light.scattering;
127             lightScatteringDensity = light.mediumDensity;
128             lightScatteringSamples = light.scatteringSamples;
129             lightScatteringMaxRandomStepOffset = light.scatteringMaxRandomStepOffset;
130             lightScatteringShadow = light.scatteringUseShadow;
131             lightDiffuse = light.diffuse;
132             lightSpecular = light.specular;
133         }
134         else
135         {
136             lightDirHg = Vector4f(0.0f, 0.0f, 1.0f, 0.0f);
137             lightColor = Color4f(1.0f, 1.0f, 1.0f, 1.0f);
138         }
139         Vector3f lightDir = (lightDirHg * state.viewMatrix).xyz;
140         setParameter("lightDirection", lightDir);
141         setParameter("lightColor", lightColor);
142         setParameter("lightEnergy", lightEnergy);
143         setParameter("lightScattering", lightScattering);
144         setParameter("lightScatteringG", lightScatteringG);
145         setParameter("lightScatteringDensity", lightScatteringDensity);
146         setParameter("lightScatteringSamples", lightScatteringSamples);
147         setParameter("lightScatteringMaxRandomStepOffset", lightScatteringMaxRandomStepOffset);
148         setParameter("lightScatteringShadow", lightScatteringShadow);
149         
150         setParameter("lightDiffuse", lightDiffuse);
151         setParameter("lightSpecular", lightSpecular);
152 
153         setParameter("time", state.localTime);
154 
155         // Texture 0 - color buffer
156         glActiveTexture(GL_TEXTURE0);
157         glBindTexture(GL_TEXTURE_2D, state.colorTexture);
158         setParameter("colorBuffer", 0);
159 
160         // Texture 1 - depth buffer
161         glActiveTexture(GL_TEXTURE1);
162         glBindTexture(GL_TEXTURE_2D, state.depthTexture);
163         setParameter("depthBuffer", 1);
164 
165         // Texture 2 - normal buffer
166         glActiveTexture(GL_TEXTURE2);
167         glBindTexture(GL_TEXTURE_2D, state.normalTexture);
168         setParameter("normalBuffer", 2);
169 
170         // Texture 3 - pbr buffer
171         glActiveTexture(GL_TEXTURE3);
172         glBindTexture(GL_TEXTURE_2D, state.pbrTexture);
173         setParameter("pbrBuffer", 3);
174 
175         // Texture 4 - shadow map
176         if (state.light)
177         {
178             if (state.light.shadowEnabled)
179             {
180                 CascadedShadowMap csm = cast(CascadedShadowMap)state.light.shadowMap;
181 
182                 glActiveTexture(GL_TEXTURE4);
183                 glBindTexture(GL_TEXTURE_2D_ARRAY, csm.depthTexture);
184                 setParameter("shadowTextureArray", 4);
185                 setParameter("shadowResolution", cast(float)csm.resolution);
186                 setParameter("shadowMatrix1", csm.area[0].shadowMatrix);
187                 setParameter("shadowMatrix2", csm.area[1].shadowMatrix);
188                 setParameter("shadowMatrix3", csm.area[2].shadowMatrix);
189                 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapCascaded");
190             }
191             else
192             {
193                 glActiveTexture(GL_TEXTURE4);
194                 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture);
195                 setParameter("shadowTextureArray", 4);
196                 setParameter("shadowMatrix1", defaultShadowMatrix);
197                 setParameter("shadowMatrix2", defaultShadowMatrix);
198                 setParameter("shadowMatrix3", defaultShadowMatrix);
199                 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone");
200             }
201         }
202 
203         // Texture 5 - occlusion buffer
204         if (glIsTexture(state.occlusionTexture))
205         {
206             glActiveTexture(GL_TEXTURE5);
207             glBindTexture(GL_TEXTURE_2D, state.occlusionTexture);
208             setParameter("occlusionBuffer", 5);
209             setParameter("haveOcclusionBuffer", true);
210         }
211         else
212         {
213             setParameter("haveOcclusionBuffer", false);
214         }
215 
216         glActiveTexture(GL_TEXTURE0);
217 
218         super.bindParameters(state);
219     }
220 
221     override void unbindParameters(GraphicsState* state)
222     {
223         super.unbindParameters(state);
224 
225         glActiveTexture(GL_TEXTURE0);
226         glBindTexture(GL_TEXTURE_2D, 0);
227 
228         glActiveTexture(GL_TEXTURE1);
229         glBindTexture(GL_TEXTURE_2D, 0);
230 
231         glActiveTexture(GL_TEXTURE2);
232         glBindTexture(GL_TEXTURE_2D, 0);
233 
234         glActiveTexture(GL_TEXTURE3);
235         glBindTexture(GL_TEXTURE_2D, 0);
236 
237         glActiveTexture(GL_TEXTURE4);
238         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
239 
240         glActiveTexture(GL_TEXTURE5);
241         glBindTexture(GL_TEXTURE_2D, 0);
242 
243         glActiveTexture(GL_TEXTURE0);
244     }
245 }