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 }