1 /* 2 Copyright (c) 2017-2018 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.graphics.shaders.standard; 29 30 import std.stdio; 31 import std.math; 32 33 import dlib.core.memory; 34 import dlib.math.vector; 35 import dlib.math.matrix; 36 import dlib.math.transformation; 37 import dlib.math.interpolation; 38 import dlib.image.color; 39 40 import dagon.core.libs; 41 import dagon.core.ownership; 42 import dagon.graphics.rc; 43 import dagon.graphics.shadow; 44 import dagon.graphics.texture; 45 import dagon.graphics.cubemap; 46 import dagon.graphics.material; 47 import dagon.graphics.shader; 48 49 class StandardShader: Shader 50 { 51 string vs = import("Standard.vs"); 52 string fs = import("Standard.fs"); 53 54 CascadedShadowMap shadowMap; 55 Matrix4x4f defaultShadowMatrix; 56 57 this(Owner o) 58 { 59 auto myProgram = New!ShaderProgram(vs, fs, this); 60 super(myProgram, o); 61 62 defaultShadowMatrix = Matrix4x4f.identity; 63 } 64 65 override void bind(RenderingContext* rc) 66 { 67 auto idiffuse = "diffuse" in rc.material.inputs; 68 auto inormal = "normal" in rc.material.inputs; 69 auto iheight = "height" in rc.material.inputs; 70 auto iroughness = "roughness" in rc.material.inputs; 71 auto imetallic = "metallic" in rc.material.inputs; 72 auto ipbr = "pbr" in rc.material.inputs; 73 auto iemission = "emission" in rc.material.inputs; 74 auto ienergy = "energy" in rc.material.inputs; 75 auto itransparency = "transparency" in rc.material.inputs; 76 auto itextureScale = "textureScale" in rc.material.inputs; 77 78 bool shadeless = rc.material.boolProp("shadeless"); 79 80 bool useShadows; 81 if (shadowMap is null) 82 useShadows = false; 83 else 84 useShadows = shadowMap.enabled && rc.material.boolProp("shadowsEnabled"); 85 86 auto iparallax = "parallax" in rc.material.inputs; 87 88 int parallaxMethod = iparallax.asInteger; 89 if (parallaxMethod > ParallaxOcclusionMapping) 90 parallaxMethod = ParallaxOcclusionMapping; 91 if (parallaxMethod < 0) 92 parallaxMethod = 0; 93 94 if (idiffuse.texture) 95 { 96 glActiveTexture(GL_TEXTURE0); 97 idiffuse.texture.bind(); 98 } 99 100 if (ipbr is null) 101 { 102 rc.material.setInput("pbr", 0.0f); 103 ipbr = "pbr" in rc.material.inputs; 104 } 105 106 if (ipbr.texture is null) 107 ipbr.texture = rc.material.makeTexture(*iroughness, *imetallic, materialInput(0.0f), materialInput(0.0f)); 108 glActiveTexture(GL_TEXTURE2); 109 ipbr.texture.bind(); 110 111 // Emission 112 if (iemission.texture) 113 { 114 glActiveTexture(GL_TEXTURE3); 115 iemission.texture.bind(); 116 117 setParameter("emissionTexture", 3); 118 setParameterSubroutine("emission", ShaderType.Fragment, "emissionMap"); 119 } 120 else 121 { 122 setParameter("emissionVector", rc.material.emission.asVector4f); 123 setParameterSubroutine("emission", ShaderType.Fragment, "emissionValue"); 124 } 125 setParameter("emissionEnergy", ienergy.asFloat); 126 127 if (rc.environment.environmentMap) 128 { 129 glActiveTexture(GL_TEXTURE4); 130 rc.environment.environmentMap.bind(); 131 } 132 133 if (useShadows) 134 { 135 glActiveTexture(GL_TEXTURE5); 136 glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMap.depthTexture); 137 } 138 139 setParameter("modelViewMatrix", rc.modelViewMatrix); 140 setParameter("projectionMatrix", rc.projectionMatrix); 141 setParameter("normalMatrix", rc.normalMatrix); 142 setParameter("viewMatrix", rc.viewMatrix); 143 setParameter("invViewMatrix", rc.invViewMatrix); 144 145 setParameter("prevModelViewProjMatrix", rc.prevModelViewProjMatrix); 146 setParameter("blurModelViewProjMatrix", rc.blurModelViewProjMatrix); 147 setParameter("blurMask", rc.blurMask); 148 149 setParameter("textureScale", itextureScale.asVector2f); 150 151 setParameter("sunDirection", rc.environment.sunDirectionEye(rc.viewMatrix)); 152 setParameter("sunColor", rc.environment.sunColor); 153 setParameter("sunEnergy", rc.environment.sunEnergy); 154 155 float transparency = 1.0f; 156 if (itransparency) 157 transparency = itransparency.asFloat; 158 setParameter("transparency", transparency); 159 160 // Diffuse 161 if (idiffuse.texture) 162 { 163 setParameter("diffuseTexture", 0); 164 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorTexture"); 165 } 166 else 167 { 168 setParameter("diffuseVector", rc.material.diffuse.asVector4f); 169 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorValue"); 170 } 171 172 // Normal/height 173 bool haveHeightMap = inormal.texture !is null; 174 if (haveHeightMap) 175 haveHeightMap = inormal.texture.image.channels == 4; 176 177 if (!haveHeightMap) 178 { 179 if (inormal.texture is null) 180 { 181 if (iheight.texture !is null) // we have height map, but no normal map 182 { 183 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 184 inormal.texture = rc.material.makeTexture(color, iheight.texture); 185 haveHeightMap = true; 186 } 187 } 188 else 189 { 190 if (iheight.texture !is null) // we have both normal and height maps 191 { 192 inormal.texture = rc.material.makeTexture(inormal.texture, iheight.texture); 193 haveHeightMap = true; 194 } 195 } 196 } 197 198 if (inormal.texture) 199 { 200 setParameter("normalTexture", 1); 201 setParameterSubroutine("normal", ShaderType.Fragment, "normalMap"); 202 203 glActiveTexture(GL_TEXTURE1); 204 inormal.texture.bind(); 205 } 206 else 207 { 208 setParameter("normalVector", rc.material.normal.asVector3f); 209 setParameterSubroutine("normal", ShaderType.Fragment, "normalValue"); 210 } 211 212 // TODO: make these material properties 213 float parallaxScale = 0.03f; 214 float parallaxBias = -0.01f; 215 setParameter("parallaxScale", parallaxScale); 216 setParameter("parallaxBias", parallaxBias); 217 218 if (haveHeightMap) 219 { 220 setParameterSubroutine("height", ShaderType.Fragment, "heightMap"); 221 } 222 else 223 { 224 float h = 0.0f; //-parallaxBias / parallaxScale; 225 setParameter("heightScalar", h); 226 setParameterSubroutine("height", ShaderType.Fragment, "heightValue"); 227 parallaxMethod = ParallaxNone; 228 } 229 230 if (parallaxMethod == ParallaxSimple) 231 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxSimple"); 232 else if (parallaxMethod == ParallaxOcclusionMapping) 233 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxOcclusionMapping"); 234 else 235 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxNone"); 236 237 // PBR 238 // TODO: pass solid values as uniforms, make subroutine for each mode 239 setParameter("pbrTexture", 2); 240 241 // Environment 242 if (rc.environment.environmentMap) 243 { 244 if (cast(Cubemap)rc.environment.environmentMap) 245 { 246 setParameter("envTextureCube", 4); 247 setParameterSubroutine("environment", ShaderType.Fragment, "environmentCubemap"); 248 } 249 else 250 { 251 setParameter("envTexture", 4); 252 setParameterSubroutine("environment", ShaderType.Fragment, "environmentTexture"); 253 } 254 } 255 else 256 { 257 setParameter("skyZenithColor", rc.environment.skyZenithColor); 258 setParameter("skyHorizonColor", rc.environment.skyHorizonColor); 259 setParameter("groundColor", rc.environment.groundColor); 260 setParameter("skyEnergy", rc.environment.skyEnergy); 261 setParameter("groundEnergy", rc.environment.groundEnergy); 262 setParameterSubroutine("environment", ShaderType.Fragment, "environmentSky"); 263 } 264 265 setParameter("environmentBrightness", rc.environment.environmentBrightness); 266 267 // Shadow map 268 if (useShadows) 269 { 270 setParameter("shadowMatrix1", shadowMap.area1.shadowMatrix); 271 setParameter("shadowMatrix2", shadowMap.area2.shadowMatrix); 272 setParameter("shadowMatrix3", shadowMap.area3.shadowMatrix); 273 274 setParameter("shadowTextureSize", cast(float)shadowMap.size); 275 setParameter("shadowTextureArray", 5); 276 277 setParameterSubroutine("shadow", ShaderType.Fragment, "shadowCSM"); 278 } 279 else 280 { 281 setParameter("shadowMatrix1", defaultShadowMatrix); 282 setParameter("shadowMatrix2", defaultShadowMatrix); 283 setParameter("shadowMatrix3", defaultShadowMatrix); 284 285 setParameterSubroutine("shadow", ShaderType.Fragment, "shadowNone"); 286 } 287 288 // BRDF 289 if (shadeless) 290 setParameterSubroutine("brdf", ShaderType.Fragment, "brdfEmission"); 291 else 292 setParameterSubroutine("brdf", ShaderType.Fragment, "brdfPBR"); 293 294 glActiveTexture(GL_TEXTURE0); 295 296 super.bind(rc); 297 } 298 299 override void unbind(RenderingContext* rc) 300 { 301 super.unbind(rc); 302 303 glActiveTexture(GL_TEXTURE0); 304 glBindTexture(GL_TEXTURE_2D, 0); 305 306 glActiveTexture(GL_TEXTURE1); 307 glBindTexture(GL_TEXTURE_2D, 0); 308 309 glActiveTexture(GL_TEXTURE2); 310 glBindTexture(GL_TEXTURE_2D, 0); 311 312 glActiveTexture(GL_TEXTURE3); 313 glBindTexture(GL_TEXTURE_2D, 0); 314 315 glActiveTexture(GL_TEXTURE4); 316 glBindTexture(GL_TEXTURE_2D, 0); 317 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 318 319 glActiveTexture(GL_TEXTURE5); 320 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 321 322 glActiveTexture(GL_TEXTURE6); 323 glBindTexture(GL_TEXTURE_2D, 0); 324 325 glActiveTexture(GL_TEXTURE7); 326 glBindTexture(GL_TEXTURE_2D, 0); 327 328 glActiveTexture(GL_TEXTURE8); 329 glBindTexture(GL_TEXTURE_2D, 0); 330 331 glActiveTexture(GL_TEXTURE0); 332 } 333 }