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