diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index 9b4a039d..ba117c19 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -239,6 +239,10 @@ idCVar r_screenshotPngCompression("r_screenshotPngCompression", "3", CVAR_RENDER idCVar r_windowResizable("r_windowResizable", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Allow resizing (and maximizing) the window (needs SDL2; with 2.0.5 or newer it's applied immediately)" ); idCVar r_vidRestartAlwaysFull( "r_vidRestartAlwaysFull", 0, CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Always do a full vid_restart (ignore 'partial' argument), e.g. when changing window size" ); +// DG: for soft particles (ported from TDM) +idCVar r_skipDepthCapture( "r_skipDepthCapture", "0", CVAR_RENDERER | CVAR_BOOL, "skip depth capture" ); // #3877 +idCVar r_useSoftParticles( "r_useSoftParticles", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "soften particle transitions when player walks through them or they cross solid geometry" ); + idCVar r_glDebugContext( "r_glDebugContext", "0", CVAR_RENDERER | CVAR_BOOL, "Enable OpenGL Debug context - requires vid_restart, needs SDL2" ); // define qgl functions diff --git a/neo/renderer/draw_arb2.cpp b/neo/renderer/draw_arb2.cpp index 5bb0e86c..7b205e99 100644 --- a/neo/renderer/draw_arb2.cpp +++ b/neo/renderer/draw_arb2.cpp @@ -346,12 +346,96 @@ static progDef_t progs[MAX_GLPROGS] = { { GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP, "arbFP_glasswarp.txt" }, // SteveL #3878: Particle softening applied by the engine - { GL_VERTEX_PROGRAM_ARB, VPROG_SOFT_PARTICLE, "soft_particle.vfp" }, // TODO: can we specify this in C++? - { GL_FRAGMENT_PROGRAM_ARB, FPROG_SOFT_PARTICLE, "soft_particle.vfp" }, + { GL_VERTEX_PROGRAM_ARB, VPROG_SOFT_PARTICLE, "soft_particle.vp" }, + { GL_FRAGMENT_PROGRAM_ARB, FPROG_SOFT_PARTICLE, "soft_particle.fp" }, // additional programs can be dynamically specified in materials }; +// DG: the following two shaders are taken from TheDarkMod 2.04 (glprogs/soft_particle.vfp) +// (C) 2005-2016 Broken Glass Studios (The Dark Mod Team) and the individual authors +// released under a revised BSD license and GPLv3 +const char* softpartVShader = "!!ARBvp1.0 \n" + "OPTION ARB_position_invariant; \n" + "# NOTE: unlike the TDM shader, the following lines use .texcoord and .color \n" + "# instead of .attrib[8] and .attrib[3], to make it work with non-nvidia drivers \n" + "MOV result.texcoord, vertex.texcoord; \n" + "MOV result.color, vertex.color; \n" + "END \n"; + +const char* softpartFShader = "!!ARBfp1.0 \n" + "# == Fragment Program == \n" + "# taken from The Dark Mod 2.04, adjusted for dhewm3 \n" + "# (C) 2005-2016 Broken Glass Studios (The Dark Mod Team) \n" + "# \n" + "# Input textures \n" + "# texture[0] particle diffusemap \n" + "# texture[1] _currentDepth \n" + "# \n" + "# Constants set by the engine: \n" + "# program.env[22] is reciprocal of _currentDepth size. Lets us convert a screen position to a texcoord in _currentDepth \n" + "# { 1.0f / depthtex.width, 1.0f / depthtex.height, float(depthtex.width)/int(depthtex.width), \n" + "# float(depthtex.height)/int(depthtex.height) } \n" + "# program.env[23] is the particle radius, given as { radius, 1/(fadeRange), 1/radius } \n" + "# fadeRange is the particle diameter for alpha blends (like smoke), but the particle radius for additive \n" + "# blends (light glares), because additive effects work differently. Fog is half as apparent when a wall \n" + "# is in the middle of it. Light glares lose no visibility when they have something to reflect off. \n" + "# program.env[24] is the color channel mask. Particles with additive blend need their RGB channels modified to blend them out. \n" + "# Particles with an alpha blend need their alpha channel modified. \n" + "# \n" + "# Hard-coded constants \n" + "# depth_consts allows us to recover the original depth in Doom units of anything in the depth \n" + "# buffer. Doom3's and thus TDM's projection matrix differs slightly from the classic projection matrix as \n" + "# it implements a \"nearly-infinite\" zFar. The matrix is hard-coded in the engine, so we use hard-coded \n" + "# constants here for efficiency. depth_consts is derived from the numbers in that matrix. \n" + "# \n" + "# next line: prevent dhewm3 from injecting gamma in shader code into this shader, \n" + "# because that looks bad when rendered with additive blending (gets too bright) \n" + "# nodhewm3gammahack \n" + "\n" + "PARAM depth_consts = { 0.33333333, -0.33316667, 0.0, 0.0 }; \n" + "PARAM particle_radius = program.env[23]; \n" + "TEMP tmp, scene_depth, particle_depth, near_fade, fade; \n" + "\n" + "# Map the fragment to a texcoord on our depth image, and sample to find scene_depth \n" + "MUL tmp.xy, fragment.position, program.env[22]; \n" + "TEX scene_depth, tmp, texture[1], 2D; \n" + "MIN scene_depth, scene_depth, 0.9994; # Required by TDM projection matrix. Equates to max recoverable \n" + " # depth of 30k units, which is enough. 0.9995 is infinite depth. \n" + " # This is needed only if there is caulk sky on show (which writes \n" + " # no depth, so leaves 1 in the depth texture). \n" + "\n" + "# Recover original depth in doom units \n" + "MAD tmp, scene_depth, depth_consts.x, depth_consts.y; \n" + "RCP scene_depth, tmp.x; \n" + "\n" + "# Convert particle depth to doom units too \n" + "MAD tmp, fragment.position.z, depth_consts.x, depth_consts.y; \n" + "RCP particle_depth, tmp.x; \n" + "\n" + "# Scale the depth difference by the particle diameter to calc an alpha \n" + "# value based on how much of the 3d volume represented by the particle \n" + "# is in front of the solid scene \n" + "ADD tmp, -scene_depth, particle_depth; # NB depth is negative. 0 at the eye, -100 at 100 units into the screen. \n" + "ADD tmp, tmp, particle_radius.x; # Add the radius so a depth difference of particle radius now equals 0 \n" + "MUL_SAT fade, tmp, particle_radius.y; # divide by the particle radius or diameter and clamp \n" + "\n" + "# Also fade if the particle is too close to our eye position, so it doesn't 'pop' in and out of view \n" + "# Start a linear fade at particle_radius distance from the particle. \n" + "MUL_SAT near_fade, particle_depth, -particle_radius.z; \n" + "\n" + "# Calculate final fade and apply the channel mask \n" + "MUL fade, near_fade, fade; \n" + "ADD_SAT fade, fade, program.env[24]; # saturate the channels that don't want modifying \n" + "\n" + "# Set the color. Multiply by vertex/fragment color as that's how the particle system fades particles in and out \n" + "TEMP oColor; \n" + "TEX oColor, fragment.texcoord, texture[0], 2D; \n" + "MUL oColor, oColor, fade; \n" + "MUL result.color, oColor, fragment.color; \n" + "\n" + "END \n"; + /* ================= R_LoadARBProgram @@ -395,27 +479,37 @@ static ID_INLINE bool isARBidentifierChar( int c ) { void R_LoadARBProgram( int progIndex ) { int ofs; int err; - idStr fullPath = "glprogs/"; - fullPath += progs[progIndex].name; - char *fileBuffer; char *buffer; char *start = NULL, *end; - common->Printf( "%s", fullPath.c_str() ); + if ( progs[progIndex].ident == VPROG_SOFT_PARTICLE || progs[progIndex].ident == FPROG_SOFT_PARTICLE ) { + // these shaders are loaded directly from a string + common->Printf( " %s", progs[progIndex].name ); + const char* srcstr = (progs[progIndex].ident == VPROG_SOFT_PARTICLE) ? softpartVShader : softpartFShader; - // load the program even if we don't support it, so - // fs_copyfiles can generate cross-platform data dumps - fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL ); - if ( !fileBuffer ) { - common->Printf( ": File not found\n" ); - return; + // copy to stack memory + buffer = (char *)_alloca( strlen( srcstr ) + 1 ); + strcpy( buffer, srcstr ); + } else { + idStr fullPath = "glprogs/"; + fullPath += progs[progIndex].name; + char *fileBuffer; + common->Printf( "%s", fullPath.c_str() ); + + // load the program even if we don't support it, so + // fs_copyfiles can generate cross-platform data dumps + fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL ); + if ( !fileBuffer ) { + common->Printf( ": File not found\n" ); + return; + } + + // copy to stack memory and free + buffer = (char *)_alloca( strlen( fileBuffer ) + 1 ); + strcpy( buffer, fileBuffer ); + fileSystem->FreeFile( fileBuffer ); } - // copy to stack memory and free - buffer = (char *)_alloca( strlen( fileBuffer ) + 1 ); - strcpy( buffer, fileBuffer ); - fileSystem->FreeFile( fileBuffer ); - if ( !glConfig.isInitialized ) { return; } @@ -465,7 +559,7 @@ void R_LoadARBProgram( int progIndex ) { // note that strlen("dhewm3tmpres") == strlen("result.color") const char* tmpres = "TEMP dhewm3tmpres; # injected by dhewm3 for gamma correction\n"; - // Note: program.env[4].xyz = r_brightness; program.env[4].w = 1.0/r_gamma + // Note: program.env[21].xyz = r_brightness; program.env[21].w = 1.0/r_gamma // outColor.rgb = pow(dhewm3tmpres.rgb*r_brightness, vec3(1.0/r_gamma)) // outColor.a = dhewm3tmpres.a; const char* extraLines = diff --git a/neo/renderer/draw_common.cpp b/neo/renderer/draw_common.cpp index 8fe96ac0..6e9118bb 100644 --- a/neo/renderer/draw_common.cpp +++ b/neo/renderer/draw_common.cpp @@ -34,8 +34,6 @@ If you have questions concerning this license or the applicable additional terms extern idCVar r_useCarmacksReverse; extern idCVar r_useStencilOpSeparate; -idCVar r_skipDepthCapture( "r_skipDepthCapture", "0", CVAR_RENDERER | CVAR_BOOL, "skip depth capture" ); // #3877 - /* ===================== RB_BakeTextureMatrixIntoTexgen @@ -952,13 +950,14 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) { qglEnableClientState( GL_COLOR_ARRAY ); } - - //GL_State( pStage->drawStateBits | GLS_DEPTHFUNC_ALWAYS ); // Disable depth clipping. The fragment program will - // handle it to allow overdraw. +#if 0 // debug stuff: render particles opaque so debug colors written in the shader are properly visible int dsbits = pStage->drawStateBits | GLS_DEPTHFUNC_ALWAYS; dsbits &= ~(GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS); //dsbits |= GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO; both values are 0, so this would be a noop GL_State( dsbits ); +#endif + GL_State( pStage->drawStateBits | GLS_DEPTHFUNC_ALWAYS ); // Disable depth clipping. The fragment program will + // handle it to allow overdraw. qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_SOFT_PARTICLE ); qglEnable( GL_VERTEX_PROGRAM_ARB ); @@ -972,6 +971,7 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) { qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_SOFT_PARTICLE ); qglEnable( GL_FRAGMENT_PROGRAM_ARB ); +#if 0 // debug stuff // Set up parameters for fragment program const char* srcblendstr = "???"; if ( src_blend >= 0 && src_blend <= 9 ) { @@ -1006,14 +1006,15 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) { #undef MY_CASE } - //printf("XX mat: %s, src_blend = %s dest_blend = %s radius = %g\n", shader->GetName(), srcblendstr, dstblend, surf->particle_radius); + printf("XX mat: %s, src_blend = %s dest_blend = %s radius = %g\n", shader->GetName(), srcblendstr, dstblend, surf->particle_radius); +#endif - // program.env[5] is the particle radius, given as { radius, 1/(faderange), 1/radius } + // program.env[23] is the particle radius, given as { radius, 1/(faderange), 1/radius } float fadeRange = 1.0f; // 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. See - // issue #3878 for diagram + // The Dark Mod issue #3878 for diagram if ( src_blend == GLS_SRCBLEND_SRC_ALPHA ) // an alpha blend material { fadeRange = surf->particle_radius * 2.0f; @@ -1031,7 +1032,7 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) { }; qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, PP_PARTICLE_RADIUS, parm ); - // program.env[6] is the color channel mask. It gets added to the fade multiplier, so adding 1 + // program.env[24] is the color channel mask. It gets added to the fade multiplier, so adding 1 // to a channel will make sure it doesn't get faded at all. Particles with additive blend // need their RGB channels modifying to blend them out. Particles with an alpha blend need // their alpha channel modifying. @@ -1045,8 +1046,6 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) { parm[0] = parm[1] = parm[2] = 0.0f; // Fade the rgb channels but parm[3] = 1.0f; // leave the alpha channel at full strength } - //parm[0] = parm[1] = parm[2] = 1.0f; // XXX hack - //parm[3] = 1.0f; // XXX hack qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, PP_PARTICLE_COLCHAN_MASK, parm ); // draw it diff --git a/neo/renderer/tr_light.cpp b/neo/renderer/tr_light.cpp index 26b7ad9c..fdd4c4cf 100644 --- a/neo/renderer/tr_light.cpp +++ b/neo/renderer/tr_light.cpp @@ -40,8 +40,6 @@ If you have questions concerning this license or the applicable additional terms static const float CHECK_BOUNDS_EPSILON = 1.0f; -static idCVar r_useSoftParticles( "r_useSoftParticles", "1", CVAR_RENDERER | CVAR_BOOL, "soften particle transitions when player walks through them or they cross solid geometry" ); - /* =========================================================================================== diff --git a/neo/renderer/tr_local.h b/neo/renderer/tr_local.h index 11029873..c19c8019 100644 --- a/neo/renderer/tr_local.h +++ b/neo/renderer/tr_local.h @@ -985,6 +985,7 @@ extern idCVar r_debugRenderToTexture; extern idCVar r_glDebugContext; // DG: use debug context to call logging callbacks on GL errors extern idCVar r_skipDepthCapture; // DG: disable capturing depth buffer, used for soft particles +extern idCVar r_useSoftParticles; /* ====================================================================