1 /*
2 Copyright (c) 2019-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.decal;
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.shader;
45 import dagon.graphics.state;
46 import dagon.render.gbuffer;
47 
48 class DecalShader: Shader
49 {
50     String vs, fs;
51 
52     GBuffer gbuffer;
53 
54     this(GBuffer gbuffer, Owner owner)
55     {
56         vs = Shader.load("data/__internal/shaders/Decal/Decal.vert.glsl");
57         fs = Shader.load("data/__internal/shaders/Decal/Decal.frag.glsl");
58 
59         auto prog = New!ShaderProgram(vs, fs, this);
60         super(prog, owner);
61 
62         this.gbuffer = gbuffer;
63     }
64 
65     ~this()
66     {
67         vs.free();
68         fs.free();
69     }
70 
71     override void bindParameters(GraphicsState* state)
72     {
73         Material mat = state.material;
74         
75         setParameter("modelViewMatrix", state.modelViewMatrix);
76         setParameter("projectionMatrix", state.projectionMatrix);
77         setParameter("invProjectionMatrix", state.invProjectionMatrix);
78         setParameter("normalMatrix", state.normalMatrix);
79         setParameter("viewMatrix", state.viewMatrix);
80         setParameter("invViewMatrix", state.invViewMatrix);
81         setParameter("invModelMatrix", state.invModelMatrix);
82         setParameter("resolution", state.resolution);
83 
84         setParameter("opacity", state.opacity * mat.opacity);
85         setParameter("textureScale", mat.textureScale);
86 
87         // Depth
88         glActiveTexture(GL_TEXTURE0);
89         glBindTexture(GL_TEXTURE_2D, gbuffer.depthTexture);
90         setParameter("depthTexture", cast(int)0);
91 
92         // Diffuse
93         glActiveTexture(GL_TEXTURE1);
94         setParameter("diffuseTexture", cast(int)1);
95         setParameter("diffuseVector", mat.baseColorFactor);
96         if (mat.baseColorTexture)
97         {
98             mat.baseColorTexture.bind();
99             setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorTexture");
100         }
101         else
102         {
103             glBindTexture(GL_TEXTURE_2D, 0);
104             setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorValue");
105         }
106         
107         if (!mat.outputColor)
108         {
109             glColorMaski(0, 0, 0, 0, 0);
110         }
111         
112         // Normal
113         glActiveTexture(GL_TEXTURE2);
114         setParameter("normalTexture", cast(int)2);
115         setParameter("normalVector", mat.normalFactor);
116         if (mat.normalTexture)
117         {
118             mat.normalTexture.bind();
119             setParameterSubroutine("normal", ShaderType.Fragment, "normalMap");
120             setParameter("generateTBN", cast(int)1);
121         }
122         else
123         {
124             glBindTexture(GL_TEXTURE_2D, 0);
125             setParameterSubroutine("normal", ShaderType.Fragment, "normalValue");
126             setParameter("generateTBN", cast(int)0);
127         }
128         
129         if (state.material.invertNormalY)
130             setParameter("normalYSign", -1.0f);
131         else
132             setParameter("normalYSign", 1.0f);
133         
134         if (!mat.outputNormal)
135         {
136             glColorMaski(1, 0, 0, 0, 0);
137         }
138         
139         // Height and parallax
140         int parallaxMethod = mat.parallaxMode;
141         if (parallaxMethod > ParallaxOcclusionMapping)
142             parallaxMethod = ParallaxOcclusionMapping;
143         if (parallaxMethod < 0)
144             parallaxMethod = 0;
145         
146         glActiveTexture(GL_TEXTURE3);
147         setParameter("heightTexture", cast(int)3);
148         setParameter("heightScalar", mat.heightFactor);
149         if (mat.heightTexture)
150         {
151             mat.heightTexture.bind();
152             setParameterSubroutine("height", ShaderType.Fragment, "heightMap");
153         }
154         else
155         {
156             glBindTexture(GL_TEXTURE_2D, 0);
157             setParameterSubroutine("height", ShaderType.Fragment, "heightValue");
158             parallaxMethod = ParallaxNone;
159         }
160         
161         if (parallaxMethod == ParallaxSimple)
162             setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxSimple");
163         else if (parallaxMethod == ParallaxOcclusionMapping)
164             setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxOcclusionMapping");
165         else
166             setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxNone");
167         
168         setParameter("parallaxScale", mat.parallaxScale);
169         setParameter("parallaxBias", mat.parallaxBias);
170         
171         // PBR
172         glActiveTexture(GL_TEXTURE4);
173         setParameter("roughnessMetallicTexture", cast(int)4);
174         setParameter("roughnessMetallicFactor", Vector4f(1.0f, mat.roughnessFactor, mat.metallicFactor, 0.0f));
175         if (mat.roughnessMetallicTexture)
176         {
177             mat.roughnessMetallicTexture.bind();
178             setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessMap");
179             setParameterSubroutine("metallic", ShaderType.Fragment, "metallicMap");
180         }
181         else
182         {
183             glBindTexture(GL_TEXTURE_2D, 0);
184             setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessValue");
185             setParameterSubroutine("metallic", ShaderType.Fragment, "metallicValue");
186         }
187         
188         if (!mat.outputPBR)
189         {
190             glColorMaski(2, 0, 0, 0, 0);
191         }
192         
193         // Emission
194         glActiveTexture(GL_TEXTURE5);
195         setParameter("emissionTexture", cast(int)5);
196         setParameter("emissionFactor", mat.emissionFactor);
197         if (mat.emissionTexture)
198         {
199             mat.emissionTexture.bind();
200             setParameterSubroutine("emission", ShaderType.Fragment, "emissionColorTexture");
201         }
202         else
203         {
204             glBindTexture(GL_TEXTURE_2D, 0);
205             setParameterSubroutine("emission", ShaderType.Fragment, "emissionColorValue");
206         }
207         setParameter("emissionEnergy", mat.emissionEnergy);
208         
209         if (!mat.outputEmission)
210         {
211             glColorMaski(3, 0, 0, 0, 0);
212         }
213 
214         glActiveTexture(GL_TEXTURE0);
215 
216         super.bindParameters(state);
217     }
218 
219     override void unbindParameters(GraphicsState* state)
220     {
221         super.unbindParameters(state);
222 
223         glColorMaski(0, 1, 1, 1, 1);
224         glColorMaski(1, 1, 1, 1, 1);
225         glColorMaski(2, 1, 1, 1, 1);
226         glColorMaski(3, 1, 1, 1, 1);
227 
228         glActiveTexture(GL_TEXTURE0);
229         glBindTexture(GL_TEXTURE_2D, 0);
230 
231         glActiveTexture(GL_TEXTURE1);
232         glBindTexture(GL_TEXTURE_2D, 0);
233 
234         glActiveTexture(GL_TEXTURE2);
235         glBindTexture(GL_TEXTURE_2D, 0);
236 
237         glActiveTexture(GL_TEXTURE3);
238         glBindTexture(GL_TEXTURE_2D, 0);
239 
240         glActiveTexture(GL_TEXTURE4);
241         glBindTexture(GL_TEXTURE_2D, 0);
242         
243         glActiveTexture(GL_TEXTURE5);
244         glBindTexture(GL_TEXTURE_2D, 0);
245 
246         glActiveTexture(GL_TEXTURE0);
247     }
248 }