#version 140 // !!ARBfp1.0 in vec4 var_color; in vec4 var_tc0; out vec4 draw_Color; uniform sampler2D u_texture0; uniform sampler2D u_texture1; uniform vec4 u_scaleDepthCoords; uniform vec4 u_softParticleBlend; uniform vec4 u_softParticleParams; 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. // vec4 depth_myconsts = vec4(0.33333333, -0.33316667, 0.0, 0.0); //PARAM depth_consts = { 0.33333333, -0.33316667, 0.0, 0.0 }; vec4 particle_radius = u_softParticleParams; //PARAM particle_radius = program.env[5]; vec4 tmp, scene_depth, particle_depth, near_fade, fade; //TEMP tmp, scene_depth, particle_depth, near_fade, fade; // Map the fragment to a texcoord on our depth image, and sample to find scene_depth tmp.xy = (gl_FragCoord.xy) * (u_scaleDepthCoords.xy); //MUL tmp.xy, fragment.position, program.env[4]; scene_depth = texture(u_texture1, tmp.xy); //TEX scene_depth, tmp, texture[1], 2D; scene_depth = min(scene_depth, vec4(0.9994)); //MIN scene_depth, scene_depth, 0.9994; // Recover original depth in doom units tmp = (scene_depth) * (depth_myconsts.xxxx) + (depth_myconsts.yyyy); //MAD tmp, scene_depth, depth_consts.x, depth_consts.y; scene_depth = vec4(1.0 / tmp.x); //RCP scene_depth, tmp.x; // Convert particle depth to doom units too tmp = (gl_FragCoord.zzzz) * (depth_myconsts.xxxx) + (depth_myconsts.yyyy); //MAD tmp, fragment.position.z, depth_consts.x, depth_consts.y; particle_depth = vec4(1.0 / tmp.x); //RCP particle_depth, tmp.x; // 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 tmp = (-scene_depth) + (particle_depth); //ADD tmp, -scene_depth, particle_depth; tmp = (tmp) + (particle_radius.xxxx); //ADD tmp, tmp, particle_radius.x; fade = clamp((tmp) * (particle_radius.yyyy), 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 particle_radius distance from the particle. near_fade = clamp((particle_depth) * (-particle_radius.zzzz), 0.0, 1.0); //MUL_SAT near_fade, particle_depth, -particle_radius.z; // Calculate final fade and apply the channel mask fade = (near_fade) * (fade); //MUL fade, near_fade, fade; fade = clamp((fade) + (u_softParticleBlend), 0.0, 1.0); //ADD_SAT fade, fade, program.env[6]; // Set the color. Multiply by vertex/fragment color as that's how the particle system fades particles in and out vec4 oColor; //TEMP oColor; oColor = texture(u_texture0, var_tc0.xy); //TEX oColor, fragment.texcoord, texture[0], 2D; oColor = (oColor) * (fade); //MUL oColor, oColor, fade; draw_Color = (oColor) * (var_color); //MUL result.color, oColor, fragment.color; }