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 }