1 /*
2 Copyright (c) 2020-2022 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.forward;
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.material;
44 import dagon.graphics.light;
45 import dagon.graphics.shader;
46 import dagon.graphics.state;
47 import dagon.graphics.texture;
48 import dagon.graphics.csm;
49 
50 class ForwardShader: Shader
51 {
52     String vs, fs;
53 
54     Matrix4x4f defaultShadowMatrix;
55     GLuint defaultShadowTexture;
56 
57     this(Owner owner)
58     {
59         vs = Shader.load("data/__internal/shaders/Forward/Forward.vert.glsl");
60         fs = Shader.load("data/__internal/shaders/Forward/Forward.frag.glsl");
61 
62         auto prog = New!ShaderProgram(vs, fs, this);
63         super(prog, owner);
64 
65         defaultShadowMatrix = Matrix4x4f.identity;
66 
67         glGenTextures(1, &defaultShadowTexture);
68         glActiveTexture(GL_TEXTURE0);
69         glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture);
70         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, 1, 1, 3, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null);
71         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
72         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
73         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
74     }
75 
76     ~this()
77     {
78         if (glIsFramebuffer(defaultShadowTexture))
79             glDeleteFramebuffers(1, &defaultShadowTexture);
80 
81         vs.free();
82         fs.free();
83     }
84 
85     override void bindParameters(GraphicsState* state)
86     {
87         Material mat = state.material;
88         
89         setParameter("modelViewMatrix", state.modelViewMatrix);
90         setParameter("projectionMatrix", state.projectionMatrix);
91         setParameter("normalMatrix", state.normalMatrix);
92         setParameter("viewMatrix", state.viewMatrix);
93         setParameter("invViewMatrix", state.invViewMatrix);
94         setParameter("prevModelViewMatrix", state.prevModelViewMatrix);
95         
96         setParameter("materialOpacity", mat.opacity);
97         setParameter("stateOpacity", state.opacity);
98         
99         setParameter("textureScale", mat.textureScale);
100         
101         setParameter("layer", cast(float)(state.layer));
102         setParameter("blurMask", state.blurMask);
103         setParameter("viewSize", state.resolution);
104 
105         // Sun
106         Light sun = mat.sun;
107         if (sun is null)
108             sun = state.environment.sun;
109         
110         Vector3f sunDirection = Vector3f(0.0f, 0.0f, 1.0f);
111         Color4f sunColor = Color4f(1.0f, 1.0f, 1.0f, 1.0f);
112         float sunEnergy = 1.0f;
113         bool sunScatteringEnabled = false;
114         float sunScatteringG = 0.0f;
115         float sunScatteringDensity = 1.0f;
116         int sunScatteringSamples = 1;
117         float sunScatteringMaxRandomStepOffset = 0.0f;
118         bool sunScatteringShadow = false;
119         bool shaded = !mat.shadeless;
120         if (sun)
121         {
122             sunDirection = sun.directionAbsolute;
123             sunColor = sun.color;
124             sunEnergy = sun.energy;
125             sunScatteringG = 1.0f - sun.scattering;
126             sunScatteringDensity = sun.mediumDensity;
127             sunScatteringEnabled = sun.scatteringEnabled;
128             sunScatteringSamples = sun.scatteringSamples;
129             sunScatteringMaxRandomStepOffset = sun.scatteringMaxRandomStepOffset;
130             sunScatteringShadow = sun.scatteringUseShadow;
131         }
132         Vector4f sunDirHg = Vector4f(sunDirection);
133         sunDirHg.w = 0.0;
134         setParameter("sunDirection", (sunDirHg * state.viewMatrix).xyz);
135         setParameter("sunColor", sunColor);
136         setParameter("sunEnergy", sunEnergy);
137         setParameter("sunScatteringG", sunScatteringG);
138         setParameter("sunScatteringDensity", sunScatteringDensity);
139         setParameter("sunScattering", sunScatteringEnabled);
140         setParameter("sunScatteringSamples", sunScatteringSamples);
141         setParameter("sunScatteringMaxRandomStepOffset", sunScatteringMaxRandomStepOffset);
142         setParameter("sunScatteringShadow", sunScatteringShadow);
143         setParameter("shaded", shaded);
144         
145         setParameter("time", state.localTime);
146         
147         setParameter("sphericalNormal", cast(int)mat.sphericalNormal);
148         
149         // Diffuse
150         glActiveTexture(GL_TEXTURE0);
151         setParameter("diffuseTexture", cast(int)0);
152         setParameter("diffuseVector", mat.baseColorFactor);
153         if (mat.baseColorTexture)
154         {
155             mat.baseColorTexture.bind();
156             setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorTexture");
157         }
158         else
159         {
160             glBindTexture(GL_TEXTURE_2D, 0);
161             setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorValue");
162         }
163 
164         // Normal/height
165         glActiveTexture(GL_TEXTURE1);
166         setParameter("normalTexture", cast(int)1);
167         setParameter("normalVector", mat.normalFactor);
168         if (mat.normalTexture)
169         {
170             mat.normalTexture.bind();
171             setParameterSubroutine("normal", ShaderType.Fragment, "normalMap");
172             setParameter("generateTBN", cast(int)1);
173         }
174         else
175         {
176             glBindTexture(GL_TEXTURE_2D, 0);
177             setParameterSubroutine("normal", ShaderType.Fragment, "normalValue");
178             setParameter("generateTBN", cast(int)0);
179         }
180         
181         if (state.material.invertNormalY)
182             setParameter("normalYSign", -1.0f);
183         else
184             setParameter("normalYSign", 1.0f);
185         
186         // PBR
187         glActiveTexture(GL_TEXTURE2);
188         setParameter("roughnessMetallicTexture", cast(int)2);
189         setParameter("roughnessMetallicFactor", Vector4f(1.0f, mat.roughnessFactor, mat.metallicFactor, 0.0f));
190         if (mat.roughnessMetallicTexture)
191         {
192             mat.roughnessMetallicTexture.bind();
193             setParameterSubroutine("specularity", ShaderType.Fragment, "specularityMap");
194             setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessMap");
195             setParameterSubroutine("metallic", ShaderType.Fragment, "metallicMap");
196         }
197         else
198         {
199             glBindTexture(GL_TEXTURE_2D, 0);
200             setParameterSubroutine("specularity", ShaderType.Fragment, "specularityValue");
201             setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessValue");
202             setParameterSubroutine("metallic", ShaderType.Fragment, "metallicValue");
203         }
204         
205         // Emission
206         glActiveTexture(GL_TEXTURE3);
207         setParameter("emissionTexture", cast(int)3);
208         setParameter("emissionFactor", mat.emissionFactor);
209         if (mat.emissionTexture)
210         {
211             mat.emissionTexture.bind();
212             setParameterSubroutine("emission", ShaderType.Fragment, "emissionMap");
213         }
214         else
215         {
216             glBindTexture(GL_TEXTURE_2D, 0);
217             setParameterSubroutine("emission", ShaderType.Fragment, "emissionValue");
218         }
219         setParameter("energy", mat.emissionEnergy);
220         
221         // Height and parallax
222         int parallaxMethod = mat.parallaxMode;
223         if (parallaxMethod > ParallaxOcclusionMapping)
224             parallaxMethod = ParallaxOcclusionMapping;
225         if (parallaxMethod < 0)
226             parallaxMethod = 0;
227         
228         glActiveTexture(GL_TEXTURE4);
229         if (mat.heightTexture)
230         {
231             mat.heightTexture.bind();
232             setParameter("heightTexture", cast(int)4);
233             setParameterSubroutine("height", ShaderType.Fragment, "heightMap");
234         }
235         else
236         {
237             glBindTexture(GL_TEXTURE_2D, 0);
238             setParameter("heightTexture", cast(int)4);
239             setParameter("heightScalar", mat.heightFactor);
240             setParameterSubroutine("height", ShaderType.Fragment, "heightValue");
241             parallaxMethod = ParallaxNone;
242         }
243         
244         if (parallaxMethod == ParallaxSimple)
245             setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxSimple");
246         else if (parallaxMethod == ParallaxOcclusionMapping)
247             setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxOcclusionMapping");
248         else
249             setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxNone");
250         
251         setParameter("parallaxScale", mat.parallaxScale);
252         setParameter("parallaxBias", mat.parallaxBias);
253 
254         // Environment map
255         if (state.environment)
256         {
257             setParameter("fogColor", state.environment.fogColor);
258             setParameter("fogStart", state.environment.fogStart);
259             setParameter("fogEnd", state.environment.fogEnd);
260             setParameter("ambientEnergy", state.environment.ambientEnergy);
261 
262             Texture ambientMap = state.environment.ambientMap;
263             if (ambientMap)
264             {
265                 if (ambientMap.isCubemap)
266                 {
267                     glActiveTexture(GL_TEXTURE5);
268                     glBindTexture(GL_TEXTURE_2D, 0);
269                     setParameter("ambientTexture", cast(int)5);
270                     
271                     glActiveTexture(GL_TEXTURE6);
272                     ambientMap.bind();
273                     setParameter("ambientTextureCube", cast(int)6);
274                     
275                     setParameterSubroutine("ambient", ShaderType.Fragment, "ambientCubemap");
276                 }
277                 else
278                 {
279                     glActiveTexture(GL_TEXTURE5);
280                     ambientMap.bind();
281                     setParameter("ambientTexture", cast(int)5);
282                     
283                     glActiveTexture(GL_TEXTURE6);
284                     glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
285                     setParameter("ambientTextureCube", cast(int)6);
286                     
287                     setParameterSubroutine("ambient", ShaderType.Fragment, "ambientEquirectangularMap");
288                 }
289             }
290             else
291             {
292                 glActiveTexture(GL_TEXTURE5);
293                 glBindTexture(GL_TEXTURE_2D, 0);
294                 setParameter("ambientTexture", cast(int)5);
295                 
296                 glActiveTexture(GL_TEXTURE6);
297                 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
298                 setParameter("ambientTextureCube", cast(int)6);
299             
300                 setParameter("ambientVector", state.environment.ambientColor.toLinear());
301                 
302                 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientColor");
303             }
304         }
305         else
306         {
307             setParameter("fogColor", Color4f(0.5f, 0.5f, 0.5f, 1.0f));
308             setParameter("fogStart", 0.0f);
309             setParameter("fogEnd", 1000.0f);
310             setParameter("ambientEnergy", 1.0f);
311             setParameter("ambientVector", Color4f(0.5f, 0.5f, 0.5f, 1.0f));
312             setParameterSubroutine("ambient", ShaderType.Fragment, "ambientColor");
313         }
314 
315         // Shadow map
316         if (sun)
317         {
318             if (sun.shadowEnabled)
319             {
320                 CascadedShadowMap csm = cast(CascadedShadowMap)sun.shadowMap;
321 
322                 glActiveTexture(GL_TEXTURE7);
323                 glBindTexture(GL_TEXTURE_2D_ARRAY, csm.depthTexture);
324                 setParameter("shadowTextureArray", cast(int)7);
325                 setParameter("shadowResolution", cast(float)csm.resolution);
326                 setParameter("shadowMatrix1", csm.area[0].shadowMatrix);
327                 setParameter("shadowMatrix2", csm.area[1].shadowMatrix);
328                 setParameter("shadowMatrix3", csm.area[2].shadowMatrix);
329                 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapCascaded");
330             }
331             else
332             {
333                 glActiveTexture(GL_TEXTURE7);
334                 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture);
335                 setParameter("shadowTextureArray", cast(int)7);
336                 setParameter("shadowMatrix1", defaultShadowMatrix);
337                 setParameter("shadowMatrix2", defaultShadowMatrix);
338                 setParameter("shadowMatrix3", defaultShadowMatrix);
339                 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone");
340             }
341         }
342         else
343         {
344             glActiveTexture(GL_TEXTURE7);
345             glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture);
346             setParameter("shadowTextureArray", cast(int)7);
347             setParameter("shadowMatrix1", defaultShadowMatrix);
348             setParameter("shadowMatrix2", defaultShadowMatrix);
349             setParameter("shadowMatrix3", defaultShadowMatrix);
350             setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone");
351         }
352         
353         // Environment BRDF LUT
354         glActiveTexture(GL_TEXTURE8);
355         if (state.environment)
356         {
357             if (state.environment.ambientBRDF)
358             {
359                 state.environment.ambientBRDF.bind();
360                 setParameter("ambientBRDF", cast(int)8);
361                 setParameter("haveAmbientBRDF", true);
362             }
363             else
364             {
365                 glBindTexture(GL_TEXTURE_2D, 0);
366                 setParameter("ambientBRDF", cast(int)8);
367                 setParameter("haveAmbientBRDF", false);
368             }
369         }
370         else
371         {
372             glBindTexture(GL_TEXTURE_2D, 0);
373             setParameter("ambientBRDF", cast(int)8);
374             setParameter("haveAmbientBRDF", false);
375         }
376 
377         super.bindParameters(state);
378     }
379 
380     override void unbindParameters(GraphicsState* state)
381     {
382         super.unbindParameters(state);
383 
384         glActiveTexture(GL_TEXTURE0);
385         glBindTexture(GL_TEXTURE_2D, 0);
386 
387         glActiveTexture(GL_TEXTURE1);
388         glBindTexture(GL_TEXTURE_2D, 0);
389 
390         glActiveTexture(GL_TEXTURE2);
391         glBindTexture(GL_TEXTURE_2D, 0);
392 
393         glActiveTexture(GL_TEXTURE3);
394         glBindTexture(GL_TEXTURE_2D, 0);
395 
396         glActiveTexture(GL_TEXTURE4);
397         glBindTexture(GL_TEXTURE_2D, 0);
398 
399         glActiveTexture(GL_TEXTURE5);
400         glBindTexture(GL_TEXTURE_2D, 0);
401         
402         glActiveTexture(GL_TEXTURE6);
403         glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
404 
405         glActiveTexture(GL_TEXTURE7);
406         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
407 
408         glActiveTexture(GL_TEXTURE0);
409     }
410 }