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