1 /* 2 Copyright (c) 2018-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.special.water; 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.texture; 45 import dagon.graphics.shader; 46 import dagon.graphics.state; 47 import dagon.graphics.cubemap; 48 import dagon.graphics.csm; 49 import dagon.render.gbuffer; 50 import dagon.resource.asset; 51 import dagon.resource.texture; 52 53 // TODO: move to dlib.math.utils 54 real frac(real v) 55 { 56 real intpart; 57 return modf(v, intpart); 58 } 59 60 class WaterShader: Shader 61 { 62 String vs, fs; 63 64 GBuffer gbuffer; 65 Texture rippleTexture; 66 Texture normalTexture1; 67 Texture normalTexture2; 68 69 Matrix4x4f defaultShadowMatrix; 70 GLuint defaultShadowTexture; 71 72 Color4f waterColor = Color4f(0.02f, 0.02f, 0.08f, 0.9f); 73 float rainIntensity = 0.1f; 74 float flowSpeed = 0.08f; 75 float waveAmplitude = 0.3f; 76 77 this(GBuffer gbuffer, AssetManager assetManager, Owner owner) 78 { 79 vs = Shader.load("data/__internal/shaders/Water/Water.vert.glsl"); 80 fs = Shader.load("data/__internal/shaders/Water/Water.frag.glsl"); 81 82 auto prog = New!ShaderProgram(vs, fs, this); 83 super(prog, owner); 84 85 this.gbuffer = gbuffer; 86 87 TextureAsset rippleTextureAsset = textureAsset(assetManager, "data/__internal/textures/ripples.png"); 88 rippleTexture = rippleTextureAsset.texture; 89 90 TextureAsset normalTexture1Asset = textureAsset(assetManager, "data/__internal/textures/water_normal1.png"); 91 normalTexture1 = normalTexture1Asset.texture; 92 93 TextureAsset normalTexture2Asset = textureAsset(assetManager, "data/__internal/textures/water_normal2.png"); 94 normalTexture2 = normalTexture2Asset.texture; 95 96 defaultShadowMatrix = Matrix4x4f.identity; 97 98 glGenTextures(1, &defaultShadowTexture); 99 glActiveTexture(GL_TEXTURE0); 100 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture); 101 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, 1, 1, 3, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null); 102 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 103 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); 104 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 105 } 106 107 ~this() 108 { 109 if (glIsFramebuffer(defaultShadowTexture)) 110 glDeleteFramebuffers(1, &defaultShadowTexture); 111 112 vs.free(); 113 fs.free(); 114 } 115 116 override void bindParameters(GraphicsState* state) 117 { 118 auto itextureScale = "textureScale" in state.material.inputs; 119 auto ishadeless = "shadeless" in state.material.inputs; 120 121 setParameter("modelViewMatrix", state.modelViewMatrix); 122 setParameter("projectionMatrix", state.projectionMatrix); 123 setParameter("invProjectionMatrix", state.invProjectionMatrix); 124 setParameter("normalMatrix", state.normalMatrix); 125 setParameter("viewMatrix", state.viewMatrix); 126 setParameter("invViewMatrix", state.invViewMatrix); 127 setParameter("prevModelViewMatrix", state.prevModelViewMatrix); 128 129 setParameter("textureScale", itextureScale.asVector2f); 130 131 setParameter("viewSize", state.resolution); 132 133 // Water props 134 setParameter("waterColor", waterColor); 135 setParameter("rainIntensity", rainIntensity); 136 setParameter("flowSpeed", flowSpeed); 137 setParameter("waveAmplitude", waveAmplitude); 138 139 // Sun 140 Vector3f sunDirection = Vector3f(0.0f, 0.0f, 1.0f); 141 Color4f sunColor = Color4f(1.0f, 1.0f, 1.0f, 1.0f); 142 float sunEnergy = 1.0f; 143 bool sunScatteringEnabled = false; 144 float sunScatteringG = 0.0f; 145 float sunScatteringDensity = 1.0f; 146 int sunScatteringSamples = 1; 147 float sunScatteringMaxRandomStepOffset = 0.0f; 148 bool shaded = !ishadeless.asBool; 149 if (state.material.sun) 150 { 151 auto sun = state.material.sun; 152 sunDirection = sun.directionAbsolute; 153 sunColor = sun.color; 154 sunEnergy = sun.energy; 155 sunScatteringG = 1.0f - sun.scattering; 156 sunScatteringDensity = sun.mediumDensity; 157 sunScatteringEnabled = sun.scatteringEnabled; 158 } 159 Vector4f sunDirHg = Vector4f(sunDirection); 160 sunDirHg.w = 0.0; 161 setParameter("sunDirection", (sunDirHg * state.viewMatrix).xyz); 162 setParameter("sunColor", sunColor); 163 setParameter("sunEnergy", sunEnergy); 164 setParameter("sunScatteringG", sunScatteringG); 165 setParameter("sunScatteringDensity", sunScatteringDensity); 166 setParameter("sunScattering", sunScatteringEnabled); 167 setParameter("sunScatteringSamples", sunScatteringSamples); 168 setParameter("sunScatteringMaxRandomStepOffset", sunScatteringMaxRandomStepOffset); 169 setParameter("shaded", shaded); 170 171 // Texture 0 - depth texture (for smooth coast transparency) 172 glActiveTexture(GL_TEXTURE0); 173 glBindTexture(GL_TEXTURE_2D, gbuffer.depthTexture); 174 setParameter("depthBuffer", 0); 175 176 // Ripple parameters 177 glActiveTexture(GL_TEXTURE1); 178 rippleTexture.bind(); 179 setParameter("rippleTexture", 1); 180 181 float rippleTimesX = frac((state.time.elapsed) * 1.6); 182 float rippleTimesY = frac((state.time.elapsed * 0.85 + 0.2) * 1.6); 183 float rippleTimesZ = frac((state.time.elapsed * 0.93 + 0.45) * 1.6); 184 float rippleTimesW = frac((state.time.elapsed * 1.13 + 0.7) * 1.6); 185 setParameter("rippleTimes", Vector4f(rippleTimesX, rippleTimesY, rippleTimesZ, rippleTimesW)); 186 187 // Environment 188 if (state.environment) 189 { 190 setParameter("fogColor", state.environment.fogColor); 191 setParameter("fogStart", state.environment.fogStart); 192 setParameter("fogEnd", state.environment.fogEnd); 193 setParameter("ambientEnergy", state.environment.ambientEnergy); 194 195 if (state.environment.ambientMap) 196 { 197 glActiveTexture(GL_TEXTURE2); 198 state.environment.ambientMap.bind(); 199 if (cast(Cubemap)state.environment.ambientMap) 200 { 201 setParameter("ambientTextureCube", 2); 202 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientCubemap"); 203 } 204 else 205 { 206 setParameter("ambientTexture", 2); 207 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientEquirectangularMap"); 208 } 209 } 210 else 211 { 212 setParameter("ambientVector", state.environment.ambientColor); 213 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientColor"); 214 } 215 } 216 else 217 { 218 setParameter("fogColor", Color4f(0.5f, 0.5f, 0.5f, 1.0f)); 219 setParameter("fogStart", 0.0f); 220 setParameter("fogEnd", 1000.0f); 221 setParameter("ambientEnergy", 1.0f); 222 setParameter("ambientVector", Color4f(0.5f, 0.5f, 0.5f, 1.0f)); 223 setParameterSubroutine("ambient", ShaderType.Fragment, "ambientColor"); 224 } 225 226 // Shadow map 227 if (state.material.sun) 228 { 229 if (state.material.sun.shadowEnabled) 230 { 231 CascadedShadowMap csm = cast(CascadedShadowMap)state.material.sun.shadowMap; 232 233 glActiveTexture(GL_TEXTURE3); 234 glBindTexture(GL_TEXTURE_2D_ARRAY, csm.depthTexture); 235 setParameter("shadowTextureArray", 3); 236 setParameter("shadowResolution", cast(float)csm.resolution); 237 setParameter("shadowMatrix1", csm.area[0].shadowMatrix); 238 setParameter("shadowMatrix2", csm.area[1].shadowMatrix); 239 setParameter("shadowMatrix3", csm.area[2].shadowMatrix); 240 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapCascaded"); 241 } 242 else 243 { 244 glActiveTexture(GL_TEXTURE3); 245 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture); 246 setParameter("shadowTextureArray", 3); 247 setParameter("shadowMatrix1", defaultShadowMatrix); 248 setParameter("shadowMatrix2", defaultShadowMatrix); 249 setParameter("shadowMatrix3", defaultShadowMatrix); 250 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone"); 251 } 252 } 253 else 254 { 255 glActiveTexture(GL_TEXTURE3); 256 glBindTexture(GL_TEXTURE_2D_ARRAY, defaultShadowTexture); 257 setParameter("shadowTextureArray", 3); 258 setParameter("shadowMatrix1", defaultShadowMatrix); 259 setParameter("shadowMatrix2", defaultShadowMatrix); 260 setParameter("shadowMatrix3", defaultShadowMatrix); 261 setParameterSubroutine("shadowMap", ShaderType.Fragment, "shadowMapNone"); 262 } 263 264 // Normal maps 265 glActiveTexture(GL_TEXTURE4); 266 normalTexture1.bind(); 267 setParameter("normalTexture1", 4); 268 269 glActiveTexture(GL_TEXTURE5); 270 normalTexture2.bind(); 271 setParameter("normalTexture2", 5); 272 273 setParameter("time", cast(float)state.time.elapsed); 274 275 super.bindParameters(state); 276 } 277 278 override void unbindParameters(GraphicsState* state) 279 { 280 super.unbindParameters(state); 281 282 glActiveTexture(GL_TEXTURE0); 283 glBindTexture(GL_TEXTURE_2D, 0); 284 285 glActiveTexture(GL_TEXTURE1); 286 glBindTexture(GL_TEXTURE_2D, 0); 287 288 glActiveTexture(GL_TEXTURE2); 289 glBindTexture(GL_TEXTURE_2D, 0); 290 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 291 292 glActiveTexture(GL_TEXTURE3); 293 glBindTexture(GL_TEXTURE_2D, 0); 294 295 glActiveTexture(GL_TEXTURE4); 296 glBindTexture(GL_TEXTURE_2D, 0); 297 298 glActiveTexture(GL_TEXTURE5); 299 glBindTexture(GL_TEXTURE_2D, 0); 300 301 glActiveTexture(GL_TEXTURE0); 302 } 303 }