1 /* 2 Copyright (c) 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.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.cubemap; 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 auto idiffuse = "diffuse" in state.material.inputs; 88 auto inormal = "normal" in state.material.inputs; 89 auto iheight = "height" in state.material.inputs; 90 auto iroughnessMetallic = "roughnessMetallic" in state.material.inputs; 91 //auto ipbr = "pbr" in state.material.inputs; 92 auto iroughness = "roughness" in state.material.inputs; 93 auto imetallic = "metallic" in state.material.inputs; 94 auto ispecularity = "specularity" in state.material.inputs; 95 auto itransparency = "transparency" in state.material.inputs; 96 auto itranslucency = "translucency" in state.material.inputs; 97 auto itextureScale = "textureScale" in state.material.inputs; 98 auto iparallax = "parallax" in state.material.inputs; 99 auto iemission = "emission" in state.material.inputs; 100 auto ienergy = "energy" in state.material.inputs; 101 auto isphericalNormal = "sphericalNormal" in state.material.inputs; 102 auto ishadeless = "shadeless" in state.material.inputs; 103 104 setParameter("modelViewMatrix", state.modelViewMatrix); 105 setParameter("projectionMatrix", state.projectionMatrix); 106 setParameter("normalMatrix", state.normalMatrix); 107 setParameter("viewMatrix", state.viewMatrix); 108 setParameter("invViewMatrix", state.invViewMatrix); 109 setParameter("prevModelViewMatrix", state.prevModelViewMatrix); 110 111 setParameter("layer", cast(float)(state.layer)); 112 113 float materialOpacity = 1.0f; 114 if (itransparency) 115 materialOpacity = itransparency.asFloat; 116 setParameter("opacity", state.opacity * materialOpacity); 117 118 setParameter("textureScale", itextureScale.asVector2f); 119 120 setParameter("viewSize", state.resolution); 121 122 // Sun 123 Light sun = state.material.sun; 124 if (sun is null) 125 sun = state.environment.sun; 126 127 Vector3f sunDirection = Vector3f(0.0f, 0.0f, 1.0f); 128 Color4f sunColor = Color4f(1.0f, 1.0f, 1.0f, 1.0f); 129 float sunEnergy = 1.0f; 130 bool sunScatteringEnabled = false; 131 float sunScatteringG = 0.0f; 132 float sunScatteringDensity = 1.0f; 133 int sunScatteringSamples = 1; 134 float sunScatteringMaxRandomStepOffset = 0.0f; 135 bool sunScatteringShadow = false; 136 bool shaded = !ishadeless.asBool; 137 if (sun) 138 { 139 sunDirection = sun.directionAbsolute; 140 sunColor = sun.color; 141 sunEnergy = sun.energy; 142 sunScatteringG = 1.0f - sun.scattering; 143 sunScatteringDensity = sun.mediumDensity; 144 sunScatteringEnabled = sun.scatteringEnabled; 145 sunScatteringSamples = sun.scatteringSamples; 146 sunScatteringMaxRandomStepOffset = sun.scatteringMaxRandomStepOffset; 147 sunScatteringShadow = sun.scatteringUseShadow; 148 } 149 Vector4f sunDirHg = Vector4f(sunDirection); 150 sunDirHg.w = 0.0; 151 setParameter("sunDirection", (sunDirHg * state.viewMatrix).xyz); 152 setParameter("sunColor", sunColor); 153 setParameter("sunEnergy", sunEnergy); 154 setParameter("sunScatteringG", sunScatteringG); 155 setParameter("sunScatteringDensity", sunScatteringDensity); 156 setParameter("sunScattering", sunScatteringEnabled); 157 setParameter("sunScatteringSamples", sunScatteringSamples); 158 setParameter("sunScatteringMaxRandomStepOffset", sunScatteringMaxRandomStepOffset); 159 setParameter("sunScatteringShadow", sunScatteringShadow); 160 setParameter("shaded", shaded); 161 162 setParameter("time", state.localTime); 163 164 // Parallax mode 165 int parallaxMethod = iparallax.asInteger; 166 if (parallaxMethod > ParallaxOcclusionMapping) 167 parallaxMethod = ParallaxOcclusionMapping; 168 if (parallaxMethod < 0) 169 parallaxMethod = 0; 170 171 setParameter("sphericalNormal", cast(int)isphericalNormal.asBool); 172 173 // Diffuse 174 if (idiffuse.texture) 175 { 176 glActiveTexture(GL_TEXTURE0); 177 idiffuse.texture.bind(); 178 setParameter("diffuseTexture", cast(int)0); 179 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorTexture"); 180 } 181 else 182 { 183 setParameter("diffuseVector", idiffuse.asVector4f); 184 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorValue"); 185 } 186 187 // Normal/height 188 bool haveHeightMap = inormal.texture !is null; 189 if (haveHeightMap) 190 haveHeightMap = inormal.texture.image.channels == 4; 191 192 if (!haveHeightMap) 193 { 194 if (inormal.texture is null) 195 { 196 if (iheight.texture !is null) // we have height map, but no normal map 197 { 198 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 199 inormal.texture = state.material.makeTexture(color, iheight.texture); 200 haveHeightMap = true; 201 } 202 } 203 else 204 { 205 if (iheight.texture !is null) // we have both normal and height maps 206 { 207 inormal.texture = state.material.makeTexture(inormal.texture, iheight.texture); 208 haveHeightMap = true; 209 } 210 } 211 } 212 213 if (inormal.texture) 214 { 215 setParameter("generateTBN", 1); 216 setParameter("normalTexture", 1); 217 setParameterSubroutine("normal", ShaderType.Fragment, "normalMap"); 218 219 glActiveTexture(GL_TEXTURE1); 220 inormal.texture.bind(); 221 } 222 else 223 { 224 setParameter("generateTBN", 0); 225 setParameter("normalVector", state.material.normal.asVector3f); 226 setParameterSubroutine("normal", ShaderType.Fragment, "normalValue"); 227 } 228 229 if (state.material.invertNormalY) 230 setParameter("normalYSign", -1.0f); 231 else 232 setParameter("normalYSign", 1.0f); 233 234 // Height and parallax 235 // TODO: make these material properties 236 float parallaxScale = 0.03f; 237 float parallaxBias = -0.01f; 238 setParameter("parallaxScale", parallaxScale); 239 setParameter("parallaxBias", parallaxBias); 240 241 if (haveHeightMap) 242 { 243 setParameterSubroutine("height", ShaderType.Fragment, "heightMap"); 244 } 245 else 246 { 247 float h = 0.0f; //-parallaxBias / parallaxScale; 248 setParameter("heightScalar", h); 249 setParameterSubroutine("height", ShaderType.Fragment, "heightValue"); 250 parallaxMethod = ParallaxNone; 251 } 252 253 if (parallaxMethod == ParallaxSimple) 254 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxSimple"); 255 else if (parallaxMethod == ParallaxOcclusionMapping) 256 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxOcclusionMapping"); 257 else 258 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxNone"); 259 260 // PBR 261 if (iroughnessMetallic is null) 262 { 263 state.material.setInput("roughnessMetallic", 0.0f); 264 iroughnessMetallic = "roughnessMetallic" in state.material.inputs; 265 } 266 if (iroughnessMetallic.texture is null) 267 { 268 iroughnessMetallic.texture = state.material.makeTexture(*ispecularity, *iroughness, *imetallic, *itranslucency); 269 } 270 glActiveTexture(GL_TEXTURE2); 271 iroughnessMetallic.texture.bind(); 272 setParameter("pbrTexture", 2); 273 274 setParameterSubroutine("specularity", ShaderType.Fragment, "specularityMap"); 275 setParameterSubroutine("metallic", ShaderType.Fragment, "metallicMap"); 276 setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessMap"); 277 278 if (itranslucency.texture is null) 279 { 280 setParameterSubroutine("translucency", ShaderType.Fragment, "translucencyValue"); 281 282 if (itranslucency.type == MaterialInputType.Float) 283 setParameter("translucencyScalar", itranslucency.asFloat); 284 else if (itranslucency.type == MaterialInputType.Bool) 285 setParameter("translucencyScalar", cast(float)itranslucency.asBool); 286 else if (itranslucency.type == MaterialInputType.Integer) 287 setParameter("translucencyScalar", cast(float)itranslucency.asInteger); 288 else if (itranslucency.type == MaterialInputType.Vec2) 289 setParameter("translucencyScalar", itranslucency.asVector2f.r); 290 else if (itranslucency.type == MaterialInputType.Vec3) 291 setParameter("translucencyScalar", itranslucency.asVector3f.r); 292 else if (itranslucency.type == MaterialInputType.Vec4) 293 setParameter("translucencyScalar", itranslucency.asVector4f.r); 294 } 295 else 296 { 297 setParameterSubroutine("translucency", ShaderType.Fragment, "translucencyMap"); 298 } 299 300 // Emission 301 if (iemission.texture) 302 { 303 glActiveTexture(GL_TEXTURE3); 304 iemission.texture.bind(); 305 setParameter("emissionTexture", cast(int)3); 306 setParameterSubroutine("emission", ShaderType.Fragment, "emissionColorTexture"); 307 } 308 else 309 { 310 setParameter("emissionVector", iemission.asVector4f); 311 setParameterSubroutine("emission", ShaderType.Fragment, "emissionColorValue"); 312 } 313 setParameter("energy", ienergy.asFloat); 314 315 // Environment 316 if (state.environment) 317 { 318 setParameter("fogColor", state.environment.fogColor); 319 setParameter("fogStart", state.environment.fogStart); 320 setParameter("fogEnd", state.environment.fogEnd); 321 setParameter("ambientEnergy", state.environment.ambientEnergy); 322 323 if (state.environment.ambientMap) 324 { 325 glActiveTexture(GL_TEXTURE4); 326 state.environment.ambientMap.bind(); 327 if (cast(Cubemap)state.environment.ambientMap) 328 { 329 setParameter("ambientTextureCube", 4); 330 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientCubemap"); 331 } 332 else 333 { 334 setParameter("ambientTexture", 4); 335 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientEquirectangularMap"); 336 } 337 } 338 else 339 { 340 setParameter("ambientVector", state.environment.ambientColor); 341 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientColor"); 342 } 343 } 344 else 345 { 346 setParameter("fogColor", Color4f(0.5f, 0.5f, 0.5f, 1.0f)); 347 setParameter("fogStart", 0.0f); 348 setParameter("fogEnd", 1000.0f); 349 setParameter("ambientEnergy", 1.0f); 350 setParameter("ambientVector", Color4f(0.5f, 0.5f, 0.5f, 1.0f)); 351 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientColor"); 352 } 353 354 // Shadow map 355 if (sun) 356 { 357 if (sun.shadowEnabled) 358 { 359 CascadedShadowMap csm = cast(CascadedShadowMap)sun.shadowMap; 360 361 glActiveTexture(GL_TEXTURE5); 362 glBindTexture(GL_TEXTURE_2D_ARRAY, csm.depthTexture); 363 setParameter("shadowTextureArray", 5); 364 setParameter("shadowResolution", cast(float)csm.resolution); 365 setParameter("shadowMatrix1", csm.area[0].shadowMatrix); 366 setParameter("shadowMatrix2", csm.area[1].shadowMatrix); 367 setParameter("shadowMatrix3", csm.area[2].shadowMatrix); 368 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapCascaded"); 369 } 370 else 371 { 372 glActiveTexture(GL_TEXTURE5); 373 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture); 374 setParameter("shadowTextureArray", 5); 375 setParameter("shadowMatrix1", defaultShadowMatrix); 376 setParameter("shadowMatrix2", defaultShadowMatrix); 377 setParameter("shadowMatrix3", defaultShadowMatrix); 378 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone"); 379 } 380 } 381 else 382 { 383 glActiveTexture(GL_TEXTURE5); 384 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture); 385 setParameter("shadowTextureArray", 5); 386 setParameter("shadowMatrix1", defaultShadowMatrix); 387 setParameter("shadowMatrix2", defaultShadowMatrix); 388 setParameter("shadowMatrix3", defaultShadowMatrix); 389 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone"); 390 } 391 392 super.bindParameters(state); 393 } 394 395 override void unbindParameters(GraphicsState* state) 396 { 397 super.unbindParameters(state); 398 399 glActiveTexture(GL_TEXTURE0); 400 glBindTexture(GL_TEXTURE_2D, 0); 401 402 glActiveTexture(GL_TEXTURE1); 403 glBindTexture(GL_TEXTURE_2D, 0); 404 405 glActiveTexture(GL_TEXTURE2); 406 glBindTexture(GL_TEXTURE_2D, 0); 407 408 glActiveTexture(GL_TEXTURE3); 409 glBindTexture(GL_TEXTURE_2D, 0); 410 411 glActiveTexture(GL_TEXTURE4); 412 glBindTexture(GL_TEXTURE_2D, 0); 413 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 414 415 glActiveTexture(GL_TEXTURE5); 416 glBindTexture(GL_TEXTURE_2D, 0); 417 418 glActiveTexture(GL_TEXTURE0); 419 } 420 }