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         if (state.light)
117         {
118             auto light = state.light;
119             lightDirHg = Vector4f(light.directionAbsolute);
120             lightDirHg.w = 0.0;
121             lightColor = light.color;
122             lightEnergy = light.energy;
123             lightScattering = light.scatteringEnabled;
124             lightScatteringG = 1.0f - light.scattering;
125             lightScatteringDensity = light.mediumDensity;
126             lightScatteringSamples = light.scatteringSamples;
127             lightScatteringMaxRandomStepOffset = light.scatteringMaxRandomStepOffset;
128             lightScatteringShadow = light.scatteringUseShadow;
129         }
130         else
131         {
132             lightDirHg = Vector4f(0.0f, 0.0f, 1.0f, 0.0f);
133             lightColor = Color4f(1.0f, 1.0f, 1.0f, 1.0f);
134         }
135         Vector3f lightDir = (lightDirHg * state.viewMatrix).xyz;
136         setParameter("lightDirection", lightDir);
137         setParameter("lightColor", lightColor);
138         setParameter("lightEnergy", lightEnergy);
139         setParameter("lightScattering", lightScattering);
140         setParameter("lightScatteringG", lightScatteringG);
141         setParameter("lightScatteringDensity", lightScatteringDensity);
142         setParameter("lightScatteringSamples", lightScatteringSamples);
143         setParameter("lightScatteringMaxRandomStepOffset", lightScatteringMaxRandomStepOffset);
144         setParameter("lightScatteringShadow", lightScatteringShadow);
145 
146         setParameter("time", state.localTime);
147 
148         // Texture 0 - color buffer
149         glActiveTexture(GL_TEXTURE0);
150         glBindTexture(GL_TEXTURE_2D, state.colorTexture);
151         setParameter("colorBuffer", 0);
152 
153         // Texture 1 - depth buffer
154         glActiveTexture(GL_TEXTURE1);
155         glBindTexture(GL_TEXTURE_2D, state.depthTexture);
156         setParameter("depthBuffer", 1);
157 
158         // Texture 2 - normal buffer
159         glActiveTexture(GL_TEXTURE2);
160         glBindTexture(GL_TEXTURE_2D, state.normalTexture);
161         setParameter("normalBuffer", 2);
162 
163         // Texture 3 - pbr buffer
164         glActiveTexture(GL_TEXTURE3);
165         glBindTexture(GL_TEXTURE_2D, state.pbrTexture);
166         setParameter("pbrBuffer", 3);
167 
168         // Texture 4 - shadow map
169         if (state.light)
170         {
171             if (state.light.shadowEnabled)
172             {
173                 CascadedShadowMap csm = cast(CascadedShadowMap)state.light.shadowMap;
174 
175                 glActiveTexture(GL_TEXTURE4);
176                 glBindTexture(GL_TEXTURE_2D_ARRAY, csm.depthTexture);
177                 setParameter("shadowTextureArray", 4);
178                 setParameter("shadowResolution", cast(float)csm.resolution);
179                 setParameter("shadowMatrix1", csm.area[0].shadowMatrix);
180                 setParameter("shadowMatrix2", csm.area[1].shadowMatrix);
181                 setParameter("shadowMatrix3", csm.area[2].shadowMatrix);
182                 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapCascaded");
183             }
184             else
185             {
186                 glActiveTexture(GL_TEXTURE4);
187                 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture);
188                 setParameter("shadowTextureArray", 4);
189                 setParameter("shadowMatrix1", defaultShadowMatrix);
190                 setParameter("shadowMatrix2", defaultShadowMatrix);
191                 setParameter("shadowMatrix3", defaultShadowMatrix);
192                 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone");
193             }
194         }
195 
196         // Texture 5 - occlusion buffer
197         if (glIsTexture(state.occlusionTexture))
198         {
199             glActiveTexture(GL_TEXTURE5);
200             glBindTexture(GL_TEXTURE_2D, state.occlusionTexture);
201             setParameter("occlusionBuffer", 5);
202             setParameter("haveOcclusionBuffer", true);
203         }
204         else
205         {
206             setParameter("haveOcclusionBuffer", false);
207         }
208 
209         glActiveTexture(GL_TEXTURE0);
210 
211         super.bindParameters(state);
212     }
213 
214     override void unbindParameters(GraphicsState* state)
215     {
216         super.unbindParameters(state);
217 
218         glActiveTexture(GL_TEXTURE0);
219         glBindTexture(GL_TEXTURE_2D, 0);
220 
221         glActiveTexture(GL_TEXTURE1);
222         glBindTexture(GL_TEXTURE_2D, 0);
223 
224         glActiveTexture(GL_TEXTURE2);
225         glBindTexture(GL_TEXTURE_2D, 0);
226 
227         glActiveTexture(GL_TEXTURE3);
228         glBindTexture(GL_TEXTURE_2D, 0);
229 
230         glActiveTexture(GL_TEXTURE4);
231         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
232 
233         glActiveTexture(GL_TEXTURE5);
234         glBindTexture(GL_TEXTURE_2D, 0);
235 
236         glActiveTexture(GL_TEXTURE0);
237     }
238 }