1 /* 2 Copyright (c) 2019-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.terrain; 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 47 class TerrainShader: Shader 48 { 49 String vs, fs; 50 51 this(Owner owner) 52 { 53 vs = Shader.load("data/__internal/shaders/Terrain/Terrain.vert.glsl"); 54 fs = Shader.load("data/__internal/shaders/Terrain/Terrain.frag.glsl"); 55 56 auto prog = New!ShaderProgram(vs, fs, this); 57 super(prog, owner); 58 } 59 60 ~this() 61 { 62 vs.free(); 63 fs.free(); 64 } 65 66 override void bindParameters(GraphicsState* state) 67 { 68 auto idiffuse1 = "diffuse" in state.material.inputs; 69 auto idiffuse2 = "diffuse2" in state.material.inputs; 70 auto idiffuse3 = "diffuse3" in state.material.inputs; 71 auto idiffuse4 = "diffuse4" in state.material.inputs; 72 73 auto inormal1 = "normal" in state.material.inputs; 74 auto inormal2 = "normal2" in state.material.inputs; 75 auto inormal3 = "normal3" in state.material.inputs; 76 auto inormal4 = "normal4" in state.material.inputs; 77 78 auto iheight1 = "height" in state.material.inputs; 79 auto iheight2 = "height2" in state.material.inputs; 80 auto iheight3 = "height3" in state.material.inputs; 81 auto iheight4 = "height4" in state.material.inputs; 82 83 auto itextureScale1 = "textureScale" in state.material.inputs; 84 auto itextureScale2 = "textureScale2" in state.material.inputs; 85 auto itextureScale3 = "textureScale3" in state.material.inputs; 86 auto itextureScale4 = "textureScale4" in state.material.inputs; 87 88 auto isplat = "splat" in state.material.inputs; 89 90 auto isplatmap1 = "splatmap1" in state.material.inputs; 91 auto isplatmap2 = "splatmap2" in state.material.inputs; 92 auto isplatmap3 = "splatmap3" in state.material.inputs; 93 auto isplatmap4 = "splatmap4" in state.material.inputs; 94 95 setParameter("modelViewMatrix", state.modelViewMatrix); 96 setParameter("projectionMatrix", state.projectionMatrix); 97 setParameter("normalMatrix", state.normalMatrix); 98 setParameter("viewMatrix", state.viewMatrix); 99 setParameter("invViewMatrix", state.invViewMatrix); 100 setParameter("prevModelViewMatrix", state.prevModelViewMatrix); 101 102 setParameter("layer", cast(float)(state.layer)); 103 setParameter("opacity", state.opacity); 104 105 setParameter("textureScale1", itextureScale1.asVector2f); 106 setParameter("textureScale2", itextureScale2.asVector2f); 107 setParameter("textureScale3", itextureScale3.asVector2f); 108 setParameter("textureScale4", itextureScale4.asVector2f); 109 /* 110 int parallaxMethod = iparallax.asInteger; 111 if (parallaxMethod > ParallaxOcclusionMapping) 112 parallaxMethod = ParallaxOcclusionMapping; 113 if (parallaxMethod < 0) 114 parallaxMethod = 0; 115 */ 116 //setParameter("sphericalNormal", cast(int)isphericalNormal.asBool); 117 118 // Diffuse 1 119 if (idiffuse1.texture) 120 { 121 glActiveTexture(GL_TEXTURE0); 122 idiffuse1.texture.bind(); 123 setParameter("diffuse1Texture", cast(int)0); 124 setParameterSubroutine("diffuse1", ShaderType.Fragment, "diffuse1ColorTexture"); 125 } 126 else 127 { 128 setParameter("diffuse1Vector", idiffuse1.asVector4f); 129 setParameterSubroutine("diffuse1", ShaderType.Fragment, "diffuse1ColorValue"); 130 } 131 132 // Normal/height 1 133 bool haveHeightMap1 = inormal1.texture !is null; 134 if (haveHeightMap1) 135 haveHeightMap1 = inormal1.texture.image.channels == 4; 136 if (!haveHeightMap1) 137 { 138 if (inormal1.texture is null) 139 { 140 if (iheight1.texture !is null) // we have height map, but no normal map 141 { 142 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 143 inormal1.texture = state.material.makeTexture(color, iheight1.texture); 144 haveHeightMap1 = true; 145 } 146 } 147 else 148 { 149 if (iheight1.texture !is null) // we have both normal and height maps 150 { 151 inormal1.texture = state.material.makeTexture(inormal1.texture, iheight1.texture); 152 haveHeightMap1 = true; 153 } 154 } 155 } 156 if (inormal1.texture) 157 { 158 setParameter("normal1Texture", 1); 159 setParameterSubroutine("normal1", ShaderType.Fragment, "normal1Map"); 160 161 glActiveTexture(GL_TEXTURE1); 162 inormal1.texture.bind(); 163 } 164 else 165 { 166 setParameter("normal1Vector", inormal1.asVector3f); 167 setParameterSubroutine("normal1", ShaderType.Fragment, "normal1Value"); 168 } 169 170 // Diffuse 2 171 if (idiffuse2.texture) 172 { 173 glActiveTexture(GL_TEXTURE2); 174 idiffuse2.texture.bind(); 175 setParameter("diffuse2Texture", cast(int)2); 176 setParameterSubroutine("diffuse2", ShaderType.Fragment, "diffuse2ColorTexture"); 177 } 178 else 179 { 180 setParameter("diffuse2Vector", idiffuse2.asVector4f); 181 setParameterSubroutine("diffuse2", ShaderType.Fragment, "diffuse2ColorValue"); 182 } 183 184 // Normal/height 2 185 bool haveHeightMap2 = inormal2.texture !is null; 186 if (haveHeightMap2) 187 haveHeightMap2 = inormal2.texture.image.channels == 4; 188 if (!haveHeightMap2) 189 { 190 if (inormal2.texture is null) 191 { 192 if (iheight2.texture !is null) // we have height map, but no normal map 193 { 194 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 195 inormal2.texture = state.material.makeTexture(color, iheight2.texture); 196 haveHeightMap2 = true; 197 } 198 } 199 else 200 { 201 if (iheight2.texture !is null) // we have both normal and height maps 202 { 203 inormal2.texture = state.material.makeTexture(inormal2.texture, iheight2.texture); 204 haveHeightMap2 = true; 205 } 206 } 207 } 208 if (inormal2.texture) 209 { 210 setParameter("normal2Texture", 3); 211 setParameterSubroutine("normal2", ShaderType.Fragment, "normal2Map"); 212 213 glActiveTexture(GL_TEXTURE3); 214 inormal2.texture.bind(); 215 } 216 else 217 { 218 setParameter("normal2Vector", inormal2.asVector3f); 219 setParameterSubroutine("normal2", ShaderType.Fragment, "normal2Value"); 220 } 221 222 // Diffuse 3 223 if (idiffuse3.texture) 224 { 225 glActiveTexture(GL_TEXTURE4); 226 idiffuse3.texture.bind(); 227 setParameter("diffuse3Texture", cast(int)4); 228 setParameterSubroutine("diffuse3", ShaderType.Fragment, "diffuse3ColorTexture"); 229 } 230 else 231 { 232 setParameter("diffuse3Vector", idiffuse3.asVector4f); 233 setParameterSubroutine("diffuse3", ShaderType.Fragment, "diffuse3ColorValue"); 234 } 235 236 // Normal/height 3 237 bool haveHeightMap3 = inormal3.texture !is null; 238 if (haveHeightMap3) 239 haveHeightMap3 = inormal3.texture.image.channels == 4; 240 if (!haveHeightMap3) 241 { 242 if (inormal3.texture is null) 243 { 244 if (iheight3.texture !is null) // we have height map, but no normal map 245 { 246 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 247 inormal3.texture = state.material.makeTexture(color, iheight3.texture); 248 haveHeightMap3 = true; 249 } 250 } 251 else 252 { 253 if (iheight3.texture !is null) // we have both normal and height maps 254 { 255 inormal3.texture = state.material.makeTexture(inormal3.texture, iheight3.texture); 256 haveHeightMap3 = true; 257 } 258 } 259 } 260 if (inormal3.texture) 261 { 262 setParameter("normal3Texture", 5); 263 setParameterSubroutine("normal3", ShaderType.Fragment, "normal3Map"); 264 265 glActiveTexture(GL_TEXTURE5); 266 inormal3.texture.bind(); 267 } 268 else 269 { 270 setParameter("normal3Vector", inormal3.asVector3f); 271 setParameterSubroutine("normal3", ShaderType.Fragment, "normal3Value"); 272 } 273 274 // Diffuse 4 275 if (idiffuse4.texture) 276 { 277 glActiveTexture(GL_TEXTURE6); 278 idiffuse4.texture.bind(); 279 setParameter("diffuse4Texture", cast(int)6); 280 setParameterSubroutine("diffuse4", ShaderType.Fragment, "diffuse4ColorTexture"); 281 } 282 else 283 { 284 setParameter("diffuse4Vector", idiffuse4.asVector4f); 285 setParameterSubroutine("diffuse4", ShaderType.Fragment, "diffuse4ColorValue"); 286 } 287 288 // Normal/height 4 289 bool haveHeightMap4 = inormal4.texture !is null; 290 if (haveHeightMap4) 291 haveHeightMap4 = inormal4.texture.image.channels == 4; 292 if (!haveHeightMap4) 293 { 294 if (inormal4.texture is null) 295 { 296 if (iheight4.texture !is null) // we have height map, but no normal map 297 { 298 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 299 inormal4.texture = state.material.makeTexture(color, iheight4.texture); 300 haveHeightMap4 = true; 301 } 302 } 303 else 304 { 305 if (iheight4.texture !is null) // we have both normal and height maps 306 { 307 inormal4.texture = state.material.makeTexture(inormal4.texture, iheight4.texture); 308 haveHeightMap4 = true; 309 } 310 } 311 } 312 if (inormal4.texture) 313 { 314 setParameter("normal4Texture", 7); 315 setParameterSubroutine("normal4", ShaderType.Fragment, "normal4Map"); 316 317 glActiveTexture(GL_TEXTURE7); 318 inormal4.texture.bind(); 319 } 320 else 321 { 322 setParameter("normal4Vector", inormal4.asVector3f); 323 setParameterSubroutine("normal4", ShaderType.Fragment, "normal4Value"); 324 } 325 326 // Splatmap 327 if (isplat is null) 328 { 329 state.material.setInput("splat", 0.0f); 330 isplat = "splat" in state.material.inputs; 331 } 332 333 // PBR 334 Vector4f rms1 = Vector4f(state.material.roughness.asFloat, state.material.metallic.asFloat, 0.0f, 1.0f); 335 Vector4f rms2 = Vector4f(state.material.roughness2.asFloat, state.material.metallic2.asFloat, 0.0f, 1.0f); 336 Vector4f rms3 = Vector4f(state.material.roughness3.asFloat, state.material.metallic3.asFloat, 0.0f, 1.0f); 337 Vector4f rms4 = Vector4f(state.material.roughness4.asFloat, state.material.metallic4.asFloat, 0.0f, 1.0f); 338 339 setParameter("rms1", rms1); 340 setParameter("rms2", rms2); 341 setParameter("rms3", rms3); 342 setParameter("rms4", rms4); 343 344 if (isplat.texture is null) 345 isplat.texture = state.material.makeTexture(*isplatmap1, *isplatmap2, *isplatmap3, *isplatmap4); 346 glActiveTexture(GL_TEXTURE8); 347 isplat.texture.bind(); 348 setParameter("splatmap", cast(int)8); 349 350 glActiveTexture(GL_TEXTURE0); 351 352 super.bindParameters(state); 353 } 354 355 override void unbindParameters(GraphicsState* state) 356 { 357 super.unbindParameters(state); 358 359 glActiveTexture(GL_TEXTURE0); 360 glBindTexture(GL_TEXTURE_2D, 0); 361 362 glActiveTexture(GL_TEXTURE1); 363 glBindTexture(GL_TEXTURE_2D, 0); 364 365 glActiveTexture(GL_TEXTURE2); 366 glBindTexture(GL_TEXTURE_2D, 0); 367 368 glActiveTexture(GL_TEXTURE3); 369 glBindTexture(GL_TEXTURE_2D, 0); 370 371 glActiveTexture(GL_TEXTURE4); 372 glBindTexture(GL_TEXTURE_2D, 0); 373 374 glActiveTexture(GL_TEXTURE5); 375 glBindTexture(GL_TEXTURE_2D, 0); 376 377 glActiveTexture(GL_TEXTURE6); 378 glBindTexture(GL_TEXTURE_2D, 0); 379 380 glActiveTexture(GL_TEXTURE7); 381 glBindTexture(GL_TEXTURE_2D, 0); 382 383 glActiveTexture(GL_TEXTURE8); 384 glBindTexture(GL_TEXTURE_2D, 0); 385 386 glActiveTexture(GL_TEXTURE0); 387 } 388 }