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