/***************************************************************************** The Dark Mod GPL Source Code This file is part of the The Dark Mod Source Code, originally based on the Doom 3 GPL Source Code as published in 2011. The Dark Mod Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. For details, see LICENSE.TXT. Project: The Dark Mod (http://www.thedarkmod.com/) ******************************************************************************/ #version 140 uniform sampler2D u_texture0; uniform sampler2D u_texture1; uniform vec4 u_scaleDepthCoords; uniform vec4 u_softParticleBlend; uniform vec4 u_softParticleParams; in vec4 var_color; in vec2 var_texCoord; out vec4 draw_Color; void main() { // == Fragment Program == // // Input textures // texture[0] particle diffusemap // texture[1] _currentDepth // // Constants set by the engine: // program.env[4] is reciprocal of _currentDepth size. Lets us convert a screen position to a texcoord in _currentDepth // program.env[5] is the particle radius, given as { radius, 1/(fadeRange), 1/radius } // fadeRange is the particle diameter for alpha blends (like smoke), but the particle radius for additive // blends (light glares), because additive effects work differently. Fog is half as apparent when a wall // is in the middle of it. Light glares lose no visibility when they have something to reflect off. // program.env[6] is the color channel mask. Particles with additive blend need their RGB channels modifying to blend them out. // Particles with an alpha blend need their alpha channel modifying. // // Hard-coded constants // depth_consts allows us to recover the original depth in Doom units of anything in the depth // buffer. TDM's projection matrix differs slightly from the classic projection matrix as it // implements a "nearly-infinite" zFar. The matrix is hard-coded in the engine, so we use hard-coded // constants here for efficiency. depth_consts is derived from the numbers in that matrix. // // fetch background depth from depth texture vec2 screenTc = gl_FragCoord.xy * u_scaleDepthCoords.xy; float sceneDepth = texture(u_texture1, screenTc).r; sceneDepth = min(sceneDepth, 0.9994); // convert depth to linear for background and particle sceneDepth = 1.0 / (sceneDepth * 0.33333333 - 0.33316667); float particleDepth = 1.0 / (gl_FragCoord.z * 0.33333333 - 0.33316667); // Scale the depth difference by the particle diameter to calc an alpha // value based on how much of the 3d volume represented by the particle // is in front of the solid scene float tmp = particleDepth - sceneDepth + u_softParticleParams.x; float sceneFade = clamp(tmp * u_softParticleParams.y, 0.0, 1.0); //MUL_SAT fade, tmp, particle_radius.y; // Also fade if the particle is too close to our eye position, so it doesn't 'pop' in and out of view // Start a linear fade at ??? distance from the particle. float nearFade = clamp(particleDepth * -u_softParticleParams.z, 0.0, 1.0); //MUL_SAT near_fade, particle_depth, -particle_radius.z; // Calculate final fade and apply the channel mask vec4 fade = clamp(vec4(sceneFade * nearFade) + u_softParticleBlend, 0.0, 1.0); // multiply color by vertex/fragment color as that's how the particle system fades particles in and out draw_Color = texture(u_texture0, var_texCoord) * fade * var_color; }