mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-02-27 06:20:54 +00:00
Merge soft particles from thedarkmod 2.04
don't really work, though
This commit is contained in:
parent
10eee1eb43
commit
41eef54611
12 changed files with 379 additions and 33 deletions
|
@ -409,6 +409,10 @@ idParticleStage *idDeclParticle::ParseParticleStage( idLexer &src ) {
|
||||||
stage->gravity = src.ParseFloat();
|
stage->gravity = src.ParseFloat();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ( !token.Icmp( "softeningRadius" ) ) { // #3878 soft particles
|
||||||
|
stage->softeningRadius = src.ParseFloat();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
src.Error( "unknown token %s\n", token.c_str() );
|
src.Error( "unknown token %s\n", token.c_str() );
|
||||||
}
|
}
|
||||||
|
@ -733,6 +737,7 @@ idParticleStage::idParticleStage( void ) {
|
||||||
hidden = false;
|
hidden = false;
|
||||||
boundsExpansion = 0.0f;
|
boundsExpansion = 0.0f;
|
||||||
bounds.Clear();
|
bounds.Clear();
|
||||||
|
softeningRadius = -2.0f; // -2 means "auto" - #3878 soft particles
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -806,6 +811,7 @@ void idParticleStage::Default() {
|
||||||
randomDistribution = true;
|
randomDistribution = true;
|
||||||
entityColor = false;
|
entityColor = false;
|
||||||
cycleMsec = ( particleLife + deadTime ) * 1000;
|
cycleMsec = ( particleLife + deadTime ) * 1000;
|
||||||
|
softeningRadius = -2.0f; // -2 means "auto" - #3878 soft particles
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -193,6 +193,16 @@ public:
|
||||||
float boundsExpansion; // user tweak to fix poorly calculated bounds
|
float boundsExpansion; // user tweak to fix poorly calculated bounds
|
||||||
|
|
||||||
idBounds bounds; // derived
|
idBounds bounds; // derived
|
||||||
|
|
||||||
|
/* Soft particles -- SteveL #3878
|
||||||
|
-2.0 is the value at initialization, meaning no user specification: "auto".
|
||||||
|
-1.0 means no change to old system: suppress soft particles, but allow modelDepthhack if specified.
|
||||||
|
0 means disable all softening for this stage, including modelDepthHack.
|
||||||
|
+ve value means apply soft particle effect, allowing overdraw up to the specified depth.
|
||||||
|
This is more flexible even when not using soft particles, as modelDepthHack
|
||||||
|
can be turned off for specific stages to stop them poking through walls.
|
||||||
|
*/
|
||||||
|
float softeningRadius;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,8 @@ public:
|
||||||
|
|
||||||
void CopyFramebuffer( int x, int y, int width, int height, bool useOversizedBuffer );
|
void CopyFramebuffer( int x, int y, int width, int height, bool useOversizedBuffer );
|
||||||
|
|
||||||
void CopyDepthbuffer( int x, int y, int width, int height );
|
void CopyDepthbuffer( int x, int y, int width, int height, bool useOversizedBuffer );
|
||||||
|
|
||||||
|
|
||||||
void UploadScratch( const byte *pic, int width, int height );
|
void UploadScratch( const byte *pic, int width, int height );
|
||||||
|
|
||||||
|
@ -417,6 +418,9 @@ public:
|
||||||
idImage * specular2DTableImage; // 2D intensity texture with our specular function with variable specularity
|
idImage * specular2DTableImage; // 2D intensity texture with our specular function with variable specularity
|
||||||
idImage * borderClampImage; // white inside, black outside
|
idImage * borderClampImage; // white inside, black outside
|
||||||
|
|
||||||
|
|
||||||
|
idImage * currentDepthImage; // #3877. Allow shaders to access scene depth
|
||||||
|
|
||||||
//--------------------------------------------------------
|
//--------------------------------------------------------
|
||||||
|
|
||||||
idImage * AllocImage( const char *name );
|
idImage * AllocImage( const char *name );
|
||||||
|
|
|
@ -1993,6 +1993,7 @@ void idImageManager::Init() {
|
||||||
accumImage = ImageFromFunction("_accum", R_RGBA8Image );
|
accumImage = ImageFromFunction("_accum", R_RGBA8Image );
|
||||||
scratchCubeMapImage = ImageFromFunction("_scratchCubeMap", makeNormalizeVectorCubeMap );
|
scratchCubeMapImage = ImageFromFunction("_scratchCubeMap", makeNormalizeVectorCubeMap );
|
||||||
currentRenderImage = ImageFromFunction("_currentRender", R_RGBA8Image );
|
currentRenderImage = ImageFromFunction("_currentRender", R_RGBA8Image );
|
||||||
|
currentDepthImage = ImageFromFunction( "_currentDepth", R_RGBA8Image ); // #3877. Allow shaders to access scene depth
|
||||||
|
|
||||||
cmdSystem->AddCommand( "reloadImages", R_ReloadImages_f, CMD_FL_RENDERER, "reloads images" );
|
cmdSystem->AddCommand( "reloadImages", R_ReloadImages_f, CMD_FL_RENDERER, "reloads images" );
|
||||||
cmdSystem->AddCommand( "listImages", R_ListImages_f, CMD_FL_RENDERER, "lists images" );
|
cmdSystem->AddCommand( "listImages", R_ListImages_f, CMD_FL_RENDERER, "lists images" );
|
||||||
|
|
|
@ -1898,26 +1898,30 @@ CopyDepthbuffer
|
||||||
This should just be part of copyFramebuffer once we have a proper image type field
|
This should just be part of copyFramebuffer once we have a proper image type field
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
void idImage::CopyDepthbuffer( int x, int y, int imageWidth, int imageHeight ) {
|
void idImage::CopyDepthbuffer( int x, int y, int imageWidth, int imageHeight, bool useOversizedBuffer )
|
||||||
Bind();
|
{
|
||||||
|
this->Bind();
|
||||||
// if the size isn't a power of 2, the image must be increased in size
|
// if the size isn't a power of 2, the image must be increased in size
|
||||||
int potWidth, potHeight;
|
int potWidth, potHeight;
|
||||||
|
|
||||||
potWidth = MakePowerOfTwo( imageWidth );
|
potWidth = MakePowerOfTwo( imageWidth );
|
||||||
potHeight = MakePowerOfTwo( imageHeight );
|
potHeight = MakePowerOfTwo( imageHeight );
|
||||||
|
GetDownsize( imageWidth, imageHeight );
|
||||||
if ( uploadWidth != potWidth || uploadHeight != potHeight ) {
|
GetDownsize( potWidth, potHeight );
|
||||||
|
// Ensure we are reading from the back buffer:
|
||||||
|
qglReadBuffer( GL_BACK );
|
||||||
|
// only resize if the current dimensions can't hold it at all,
|
||||||
|
// otherwise subview renderings could thrash this
|
||||||
|
if ( ( useOversizedBuffer && ( uploadWidth < potWidth || uploadHeight < potHeight ) ) || ( !useOversizedBuffer && ( uploadWidth != potWidth || uploadHeight != potHeight ) ) )
|
||||||
|
{
|
||||||
uploadWidth = potWidth;
|
uploadWidth = potWidth;
|
||||||
uploadHeight = potHeight;
|
uploadHeight = potHeight;
|
||||||
if ( potWidth == imageWidth && potHeight == imageHeight ) {
|
// This bit runs once only at map start, because it tests whether the image is too small to hold the screen.
|
||||||
qglCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, x, y, imageWidth, imageHeight, 0 );
|
// It resizes the texture to a power of two that can hold the screen,
|
||||||
} else {
|
// and then subsequent captures to the texture put the depth component into the RGB channels
|
||||||
// we need to create a dummy image with power of two dimensions,
|
qglTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, potWidth, potHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||||
// then do a qglCopyTexSubImage2D of the data we want
|
|
||||||
qglTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, potWidth, potHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
|
||||||
qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, x, y, imageWidth, imageHeight );
|
qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, x, y, imageWidth, imageHeight );
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
||||||
// it and don't try and do a texture compression or some other silliness
|
// it and don't try and do a texture compression or some other silliness
|
||||||
|
|
|
@ -1434,6 +1434,10 @@ void idMaterial::ParseStage( idLexer &src, const textureRepeat_t trpDefault ) {
|
||||||
ss->drawStateBits |= GLS_DEPTHMASK;
|
ss->drawStateBits |= GLS_DEPTHMASK;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ( !token.Icmp( "ignoreDepth" ) ) { // Added in #3877.
|
||||||
|
ss->drawStateBits |= GLS_DEPTHFUNC_ALWAYS;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ( !token.Icmp( "alphaTest" ) ) {
|
if ( !token.Icmp( "alphaTest" ) ) {
|
||||||
ss->hasAlphaTest = true;
|
ss->hasAlphaTest = true;
|
||||||
ss->alphaTestRegister = ParseExpression( src );
|
ss->alphaTestRegister = ParseExpression( src );
|
||||||
|
|
|
@ -302,8 +302,13 @@ public:
|
||||||
virtual float DepthHack() const;
|
virtual float DepthHack() const;
|
||||||
virtual int Memory() const;
|
virtual int Memory() const;
|
||||||
|
|
||||||
|
float SofteningRadius( const int stage ) const; // #3878 soft particles
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetSofteningRadii(); // #3878 soft particles
|
||||||
|
|
||||||
const idDeclParticle * particleSystem;
|
const idDeclParticle * particleSystem;
|
||||||
|
idList<float> softeningRadii; // #3878 soft particles
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -50,6 +50,7 @@ idRenderModelPrt::InitFromFile
|
||||||
void idRenderModelPrt::InitFromFile( const char *fileName ) {
|
void idRenderModelPrt::InitFromFile( const char *fileName ) {
|
||||||
name = fileName;
|
name = fileName;
|
||||||
particleSystem = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, fileName ) );
|
particleSystem = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, fileName ) );
|
||||||
|
SetSofteningRadii(); // # 3878
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -286,3 +287,64 @@ int idRenderModelPrt::Memory() const {
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
idRenderModelPrt::SetSofteningRadii
|
||||||
|
|
||||||
|
Calculate "depth" of each particle stage that represents a 3d volume, so the particle can
|
||||||
|
be allowed to overdraw solid geometry by the right amount, and the particle "thickness" (visibility)
|
||||||
|
can be adjusted by how much of it is visible in front of the background surface.
|
||||||
|
|
||||||
|
"depth" is by default 0.8 of the particle radius, and particles less than 2 units in size won't be softened.
|
||||||
|
The particles that represent 3d volumes are the view-aligned ones. Others have depth set to 0.
|
||||||
|
|
||||||
|
Cache these values rather than calculate them for each stage every frame.
|
||||||
|
Added for soft particles -- SteveL #3878.
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
void idRenderModelPrt::SetSofteningRadii()
|
||||||
|
{
|
||||||
|
softeningRadii.AssureSize( particleSystem->stages.Num() );
|
||||||
|
|
||||||
|
for ( int i = 0; i < particleSystem->stages.Num(); ++i )
|
||||||
|
{
|
||||||
|
const idParticleStage* ps = particleSystem->stages[i];
|
||||||
|
if ( ps->softeningRadius > -2.0f ) // User has specified a setting
|
||||||
|
{
|
||||||
|
softeningRadii[i] = ps->softeningRadius;
|
||||||
|
}
|
||||||
|
else if ( ps->orientation == POR_VIEW ) // Only view-aligned particle stages qualify for softening
|
||||||
|
{
|
||||||
|
float diameter = Max( ps->size.from, ps->size.to );
|
||||||
|
float scale = Max( ps->aspect.from, ps->aspect.to );
|
||||||
|
diameter *= Max( scale, 1.0f ); // aspect applies to 1 axis only. If it's < 1, the other axis will still be at scale 1
|
||||||
|
if ( diameter > 2.0f ) // Particle is big enough to soften
|
||||||
|
{
|
||||||
|
softeningRadii[i] = diameter * 0.8f / 2.0f;
|
||||||
|
}
|
||||||
|
else // Particle is small. Disable both softening and modelDepthHack
|
||||||
|
{
|
||||||
|
softeningRadii[i] = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Particle isn't view-aligned, and no user setting. Don't change anything.
|
||||||
|
{
|
||||||
|
softeningRadii[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
idRenderModelPrt::SofteningRadius
|
||||||
|
|
||||||
|
Return the max radius of the individual quads that make up this stage.
|
||||||
|
Added for soft particles #3878.
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
float idRenderModelPrt::SofteningRadius( const int stage ) const {
|
||||||
|
assert( particleSystem );
|
||||||
|
assert( stage > -1 && stage < softeningRadii.Num() );
|
||||||
|
return softeningRadii[stage];
|
||||||
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ void RB_ARB2_DrawInteraction( const drawInteraction_t *din ) {
|
||||||
float parm[4];
|
float parm[4];
|
||||||
parm[0] = parm[1] = parm[2] = r_brightness.GetFloat();
|
parm[0] = parm[1] = parm[2] = r_brightness.GetFloat();
|
||||||
parm[3] = 1.0/r_gamma.GetFloat(); // 1.0/gamma so the shader doesn't have to do this calculation
|
parm[3] = 1.0/r_gamma.GetFloat(); // 1.0/gamma so the shader doesn't have to do this calculation
|
||||||
qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 4, parm );
|
qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, PP_GAMMA_BRIGHTNESS, parm );
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the textures
|
// set the textures
|
||||||
|
@ -345,6 +345,10 @@ static progDef_t progs[MAX_GLPROGS] = {
|
||||||
{ GL_VERTEX_PROGRAM_ARB, VPROG_GLASSWARP, "arbVP_glasswarp.txt" },
|
{ GL_VERTEX_PROGRAM_ARB, VPROG_GLASSWARP, "arbVP_glasswarp.txt" },
|
||||||
{ GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP, "arbFP_glasswarp.txt" },
|
{ 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" },
|
||||||
|
|
||||||
// additional programs can be dynamically specified in materials
|
// additional programs can be dynamically specified in materials
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -468,10 +472,10 @@ void R_LoadARBProgram( int progIndex ) {
|
||||||
// POW might not work with a negative base (it looks wrong with intel's Linux driver)
|
// POW might not work with a negative base (it looks wrong with intel's Linux driver)
|
||||||
// and clamping values >1 to 1 is ok because when writing to result.color
|
// and clamping values >1 to 1 is ok because when writing to result.color
|
||||||
// it's clamped anyway and pow(base, exp) is always >= 1 for base >= 1
|
// it's clamped anyway and pow(base, exp) is always >= 1 for base >= 1
|
||||||
"MUL_SAT dhewm3tmpres.xyz, program.env[4], dhewm3tmpres;\n" // first multiply with brightness
|
"MUL_SAT dhewm3tmpres.xyz, program.env[21], dhewm3tmpres;\n" // first multiply with brightness
|
||||||
"POW result.color.x, dhewm3tmpres.x, program.env[4].w;\n" // then do pow(dhewm3tmpres.xyz, vec3(1/gamma))
|
"POW result.color.x, dhewm3tmpres.x, program.env[21].w;\n" // then do pow(dhewm3tmpres.xyz, vec3(1/gamma))
|
||||||
"POW result.color.y, dhewm3tmpres.y, program.env[4].w;\n" // (apparently POW only supports scalars, not whole vectors)
|
"POW result.color.y, dhewm3tmpres.y, program.env[21].w;\n" // (apparently POW only supports scalars, not whole vectors)
|
||||||
"POW result.color.z, dhewm3tmpres.z, program.env[4].w;\n"
|
"POW result.color.z, dhewm3tmpres.z, program.env[21].w;\n"
|
||||||
"MOV result.color.w, dhewm3tmpres.w;\n" // alpha remains unmodified
|
"MOV result.color.w, dhewm3tmpres.w;\n" // alpha remains unmodified
|
||||||
"\nEND\n\n"; // we add this block right at the end, replacing the original "END" string
|
"\nEND\n\n"; // we add this block right at the end, replacing the original "END" string
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,9 @@ If you have questions concerning this license or the applicable additional terms
|
||||||
|
|
||||||
extern idCVar r_useCarmacksReverse;
|
extern idCVar r_useCarmacksReverse;
|
||||||
extern idCVar r_useStencilOpSeparate;
|
extern idCVar r_useStencilOpSeparate;
|
||||||
|
|
||||||
|
idCVar r_skipDepthCapture( "r_skipDepthCapture", "0", CVAR_RENDERER | CVAR_BOOL, "skip depth capture" ); // #3877
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
RB_BakeTextureMatrixIntoTexgen
|
RB_BakeTextureMatrixIntoTexgen
|
||||||
|
@ -313,7 +316,7 @@ void RB_FinishStageTexturing( const shaderStage_t *pStage, const drawSurf_t *sur
|
||||||
qglDisable( GL_FRAGMENT_PROGRAM_ARB );
|
qglDisable( GL_FRAGMENT_PROGRAM_ARB );
|
||||||
qglDisable( GL_VERTEX_PROGRAM_ARB );
|
qglDisable( GL_VERTEX_PROGRAM_ARB );
|
||||||
// Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
|
// Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
|
||||||
qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 );
|
qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 ); // FIXME ...
|
||||||
} else {
|
} else {
|
||||||
qglDisable( GL_TEXTURE_GEN_S );
|
qglDisable( GL_TEXTURE_GEN_S );
|
||||||
qglDisable( GL_TEXTURE_GEN_T );
|
qglDisable( GL_TEXTURE_GEN_T );
|
||||||
|
@ -513,6 +516,9 @@ void RB_T_FillDepthBuffer( const drawSurf_t *surf ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RB_SetProgramEnvironment( bool isPostProcess ); // so RB_STD_FillDepthBuffer() can use it
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
RB_STD_FillDepthBuffer
|
RB_STD_FillDepthBuffer
|
||||||
|
@ -553,6 +559,19 @@ void RB_STD_FillDepthBuffer( drawSurf_t **drawSurfs, int numDrawSurfs ) {
|
||||||
|
|
||||||
RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_T_FillDepthBuffer );
|
RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_T_FillDepthBuffer );
|
||||||
|
|
||||||
|
// Make the early depth pass available to shaders. #3877
|
||||||
|
if ( backEnd.viewDef->renderView.viewID >= 0 // Suppress for lightgem rendering passes
|
||||||
|
&& !r_skipDepthCapture.GetBool() )
|
||||||
|
{
|
||||||
|
globalImages->currentDepthImage->CopyDepthbuffer( backEnd.viewDef->viewport.x1,
|
||||||
|
backEnd.viewDef->viewport.y1,
|
||||||
|
backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1,
|
||||||
|
backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1,
|
||||||
|
true );
|
||||||
|
bool isPostProcess = false; // TODO
|
||||||
|
RB_SetProgramEnvironment( isPostProcess );
|
||||||
|
}
|
||||||
|
|
||||||
if ( backEnd.viewDef->numClipPlanes ) {
|
if ( backEnd.viewDef->numClipPlanes ) {
|
||||||
GL_SelectTexture( 1 );
|
GL_SelectTexture( 1 );
|
||||||
globalImages->BindNull();
|
globalImages->BindNull();
|
||||||
|
@ -575,6 +594,19 @@ SHADER PASSES
|
||||||
RB_SetProgramEnvironment
|
RB_SetProgramEnvironment
|
||||||
|
|
||||||
Sets variables that can be used by all vertex programs
|
Sets variables that can be used by all vertex programs
|
||||||
|
|
||||||
|
[SteveL #3877] Note on the use of fragment program environmental variables.
|
||||||
|
Parameters 0 and 1 are set here to allow conversion of screen coordinates to
|
||||||
|
texture coordinates, for use when sampling _currentRender.
|
||||||
|
Those same parameters 0 and 1, plus 2 and 3, are given entirely different
|
||||||
|
meanings in draw_arb2.cpp while light interactions are being drawn.
|
||||||
|
This function is called again before currentRender size is needed by post processing
|
||||||
|
effects are done, so there's no clash.
|
||||||
|
// TODO: I'm using 4 for gamma in shaders, so the following shit must be incremented by 1
|
||||||
|
Only parameters 0..3 were in use before #3877 - and in dhewm3 also 4, for gamma in shader.
|
||||||
|
Now I've used a new parameter 5 for the size of _currentDepth. It's needed throughout,
|
||||||
|
including by light interactions, and its size might in theory differ from _currentRender.
|
||||||
|
Parameters 6 and 7 are used by soft particles #3878. Note these can be freely reused by different draw calls.
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void RB_SetProgramEnvironment( bool isPostProcess ) {
|
void RB_SetProgramEnvironment( bool isPostProcess ) {
|
||||||
|
@ -643,9 +675,23 @@ void RB_SetProgramEnvironment( bool isPostProcess ) {
|
||||||
// (setting them to 1.0 makes them no-ops)
|
// (setting them to 1.0 makes them no-ops)
|
||||||
parm[0] = parm[1] = parm[2] = parm[3] = 1.0f;
|
parm[0] = parm[1] = parm[2] = parm[3] = 1.0f;
|
||||||
}
|
}
|
||||||
qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 4, parm );
|
qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, PP_GAMMA_BRIGHTNESS, parm );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #3877: Allow shaders to access depth buffer.
|
||||||
|
// Two useful ratios are packed into this parm: [0] and [1] hold the x,y multipliers you need to map a screen
|
||||||
|
// coordinate (fragment position) to the depth image: those are simply the reciprocal of the depth
|
||||||
|
// image size, which has been rounded up to a power of two. Slots [3] and [4] hold the ratio of the depth image
|
||||||
|
// size to the current render image size. These sizes can differ if the game crops the render viewport temporarily
|
||||||
|
// during post-processing effects. The depth render is smaller during the effect too, but the depth image doesn't
|
||||||
|
// need to be downsized, whereas the current render image does get downsized when it's captured by the game after
|
||||||
|
// the skybox render pass. The ratio is needed to map between the two render images.
|
||||||
|
parm[0] = 1.0f / globalImages->currentDepthImage->uploadWidth;
|
||||||
|
parm[1] = 1.0f / globalImages->currentDepthImage->uploadHeight;
|
||||||
|
parm[2] = static_cast<float>(globalImages->currentRenderImage->uploadWidth) / globalImages->currentDepthImage->uploadWidth;
|
||||||
|
parm[3] = static_cast<float>(globalImages->currentRenderImage->uploadHeight) / globalImages->currentDepthImage->uploadHeight;
|
||||||
|
qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, PP_CURDEPTH_RECIPR, parm );
|
||||||
|
|
||||||
//
|
//
|
||||||
// set eye position in global space
|
// set eye position in global space
|
||||||
//
|
//
|
||||||
|
@ -654,8 +700,6 @@ void RB_SetProgramEnvironment( bool isPostProcess ) {
|
||||||
parm[2] = backEnd.viewDef->renderView.vieworg[2];
|
parm[2] = backEnd.viewDef->renderView.vieworg[2];
|
||||||
parm[3] = 1.0;
|
parm[3] = 1.0;
|
||||||
qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 1, parm );
|
qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 1, parm );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -749,6 +793,9 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check whether we're drawing a soft particle surface #3878
|
||||||
|
const bool soft_particle = ( surf->dsFlags & DSF_SOFT_PARTICLE ) != 0;
|
||||||
|
|
||||||
// get the expressions for conditionals / color / texcoords
|
// get the expressions for conditionals / color / texcoords
|
||||||
regs = surf->shaderRegisters;
|
regs = surf->shaderRegisters;
|
||||||
|
|
||||||
|
@ -765,7 +812,8 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
|
||||||
RB_EnterWeaponDepthHack();
|
RB_EnterWeaponDepthHack();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( surf->space->modelDepthHack != 0.0f ) {
|
if ( surf->space->modelDepthHack != 0.0f && !soft_particle ) // #3878 soft particles don't want modelDepthHack, which is
|
||||||
|
{ // an older way to slightly "soften" particles
|
||||||
RB_EnterModelDepthHack( surf->space->modelDepthHack );
|
RB_EnterModelDepthHack( surf->space->modelDepthHack );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,6 +839,9 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// determine the blend mode (used by soft particles #3878)
|
||||||
|
const int src_blend = pStage->drawStateBits & GLS_SRCBLEND_BITS;
|
||||||
|
|
||||||
// see if we are a new-style stage
|
// see if we are a new-style stage
|
||||||
newShaderStage_t *newStage = pStage->newStage;
|
newShaderStage_t *newStage = pStage->newStage;
|
||||||
if ( newStage ) {
|
if ( newStage ) {
|
||||||
|
@ -866,7 +917,7 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
|
||||||
qglDisable( GL_VERTEX_PROGRAM_ARB );
|
qglDisable( GL_VERTEX_PROGRAM_ARB );
|
||||||
qglDisable( GL_FRAGMENT_PROGRAM_ARB );
|
qglDisable( GL_FRAGMENT_PROGRAM_ARB );
|
||||||
// Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
|
// Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
|
||||||
qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 );
|
qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 ); // FIXME: ...
|
||||||
|
|
||||||
qglDisableClientState( GL_COLOR_ARRAY );
|
qglDisableClientState( GL_COLOR_ARRAY );
|
||||||
qglDisableVertexAttribArrayARB( 9 );
|
qglDisableVertexAttribArrayARB( 9 );
|
||||||
|
@ -874,6 +925,142 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
|
||||||
qglDisableClientState( GL_NORMAL_ARRAY );
|
qglDisableClientState( GL_NORMAL_ARRAY );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if ( soft_particle
|
||||||
|
&& surf->particle_radius > 0.0f
|
||||||
|
&& ( src_blend == GLS_SRCBLEND_ONE || src_blend == GLS_SRCBLEND_SRC_ALPHA )
|
||||||
|
&& tr.backEndRenderer == BE_ARB2
|
||||||
|
&& !r_skipNewAmbient.GetBool() )
|
||||||
|
{
|
||||||
|
// SteveL #3878. Particles are automatically softened by the engine, unless they have shader programs of
|
||||||
|
// their own (i.e. are "newstages" handled above). This section comes after the newstage part so that if a
|
||||||
|
// designer has specified their own shader programs, those will be used instead of the soft particle program.
|
||||||
|
if ( pStage->vertexColor == SVC_IGNORE )
|
||||||
|
{
|
||||||
|
// Ignoring vertexColor is not recommended for particles. The particle system uses vertexColor for fading.
|
||||||
|
// However, there are existing particle effects that don't use it, in which case we default to using the
|
||||||
|
// rgb color modulation specified in the material like the "old stages" do below.
|
||||||
|
color[0] = regs[pStage->color.registers[0]];
|
||||||
|
color[1] = regs[pStage->color.registers[1]];
|
||||||
|
color[2] = regs[pStage->color.registers[2]];
|
||||||
|
color[3] = regs[pStage->color.registers[3]];
|
||||||
|
qglColor4fv( color );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A properly set-up particle shader
|
||||||
|
qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), (void *)&ac->color );
|
||||||
|
qglEnableClientState( GL_COLOR_ARRAY );
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_State( pStage->drawStateBits | GLS_DEPTHFUNC_ALWAYS ); // Disable depth clipping. The fragment program will
|
||||||
|
// handle it to allow overdraw.
|
||||||
|
//GL_State( pStage->drawStateBits );
|
||||||
|
|
||||||
|
qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_SOFT_PARTICLE );
|
||||||
|
qglEnable( GL_VERTEX_PROGRAM_ARB );
|
||||||
|
|
||||||
|
// Bind image and _currentDepth
|
||||||
|
GL_SelectTexture( 0 );
|
||||||
|
pStage->texture.image->Bind();
|
||||||
|
GL_SelectTexture( 1 );
|
||||||
|
globalImages->currentDepthImage->Bind();
|
||||||
|
|
||||||
|
qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_SOFT_PARTICLE );
|
||||||
|
qglEnable( GL_FRAGMENT_PROGRAM_ARB );
|
||||||
|
|
||||||
|
// Set up parameters for fragment program
|
||||||
|
const char* srcblendstr = "???";
|
||||||
|
if ( src_blend >= 0 && src_blend <= 9 ) {
|
||||||
|
const char* blendModes[] = {
|
||||||
|
"ONE",
|
||||||
|
"ZERO",
|
||||||
|
"!! INVALID !!",
|
||||||
|
"DST_COLOR",
|
||||||
|
"ONE_MINUS_DST_COLOR",
|
||||||
|
"SRC_ALPHA",
|
||||||
|
"ONE_MINUS_SRC_ALPHA",
|
||||||
|
"DST_ALPHA",
|
||||||
|
"ONE_MINUS_DST_ALPHA",
|
||||||
|
"ALPHA_SATURATE"
|
||||||
|
};
|
||||||
|
srcblendstr = blendModes[src_blend];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int dst_blend =
|
||||||
|
|
||||||
|
const int GLS_DSTBLEND_ZERO = 0x0;
|
||||||
|
const int GLS_DSTBLEND_ONE = 0x00000020;
|
||||||
|
const int GLS_DSTBLEND_SRC_COLOR = 0x00000030;
|
||||||
|
const int GLS_DSTBLEND_ONE_MINUS_SRC_COLOR = 0x00000040;
|
||||||
|
const int GLS_DSTBLEND_SRC_ALPHA = 0x00000050;
|
||||||
|
const int GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA = 0x00000060;
|
||||||
|
const int GLS_DSTBLEND_DST_ALPHA = 0x00000070;
|
||||||
|
const int GLS_DSTBLEND_ONE_MINUS_DST_ALPHA = 0x00000080;
|
||||||
|
const int GLS_DSTBLEND_BITS = 0x000000f0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
printf("XX mat: %s (%s), src_blend = %d (%s)\n", shader->GetName(), shader->GetDescription(), src_blend, srcblendstr);
|
||||||
|
|
||||||
|
// program.env[5] is the particle radius, given as { radius, 1/(faderange), 1/radius }
|
||||||
|
float fadeRange;
|
||||||
|
// 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
|
||||||
|
if ( src_blend == GLS_SRCBLEND_SRC_ALPHA ) // an alpha blend material
|
||||||
|
{
|
||||||
|
fadeRange = surf->particle_radius * 2.0f;
|
||||||
|
}
|
||||||
|
else if ( src_blend == GLS_SRCBLEND_ONE ) // an additive (blend add) material
|
||||||
|
{
|
||||||
|
fadeRange = surf->particle_radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
float parm[4] = {
|
||||||
|
surf->particle_radius,
|
||||||
|
1.0f / ( fadeRange ),
|
||||||
|
1.0f / surf->particle_radius,
|
||||||
|
0.0f
|
||||||
|
};
|
||||||
|
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
|
||||||
|
// 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.
|
||||||
|
if ( src_blend == GLS_SRCBLEND_SRC_ALPHA ) // an alpha blend material
|
||||||
|
{
|
||||||
|
parm[0] = parm[1] = parm[2] = 1.0f; // Leave the rgb channels at full strength when fading
|
||||||
|
parm[3] = 0.0f; // but fade the alpha channel
|
||||||
|
}
|
||||||
|
else if ( src_blend == GLS_SRCBLEND_ONE ) // an additive (blend add) material
|
||||||
|
{
|
||||||
|
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] = 0.0f; // XXX hack
|
||||||
|
//parm[3] = 1.0f; // XXX hack
|
||||||
|
qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, PP_PARTICLE_COLCHAN_MASK, parm );
|
||||||
|
|
||||||
|
// draw it
|
||||||
|
RB_DrawElementsWithCounters( tri );
|
||||||
|
|
||||||
|
// Clean up GL state
|
||||||
|
GL_SelectTexture( 1 );
|
||||||
|
globalImages->BindNull();
|
||||||
|
GL_SelectTexture( 0 );
|
||||||
|
globalImages->BindNull();
|
||||||
|
|
||||||
|
qglDisable( GL_VERTEX_PROGRAM_ARB );
|
||||||
|
qglDisable( GL_FRAGMENT_PROGRAM_ARB );
|
||||||
|
|
||||||
|
if ( pStage->vertexColor != SVC_IGNORE ) {
|
||||||
|
qglDisableClientState( GL_COLOR_ARRAY );
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------
|
//--------------------------
|
||||||
//
|
//
|
||||||
|
@ -972,7 +1159,8 @@ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
|
||||||
if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
|
if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
|
||||||
qglDisable( GL_POLYGON_OFFSET_FILL );
|
qglDisable( GL_POLYGON_OFFSET_FILL );
|
||||||
}
|
}
|
||||||
if ( surf->space->weaponDepthHack || surf->space->modelDepthHack != 0.0f ) {
|
if ( surf->space->weaponDepthHack || ( !soft_particle && surf->space->modelDepthHack != 0.0f ) ) // #3878 soft particles
|
||||||
|
{
|
||||||
RB_LeaveDepthHack();
|
RB_LeaveDepthHack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,13 @@ If you have questions concerning this license or the applicable additional terms
|
||||||
|
|
||||||
#include "renderer/tr_local.h"
|
#include "renderer/tr_local.h"
|
||||||
|
|
||||||
|
#include "Model_local.h"
|
||||||
|
|
||||||
|
|
||||||
static const float CHECK_BOUNDS_EPSILON = 1.0f;
|
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" );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===========================================================================================
|
===========================================================================================
|
||||||
|
|
||||||
|
@ -673,6 +678,8 @@ void R_LinkLightSurf( const drawSurf_t **link, const srfTriangles_t *tri, const
|
||||||
drawSurf->material = shader;
|
drawSurf->material = shader;
|
||||||
drawSurf->scissorRect = scissor;
|
drawSurf->scissorRect = scissor;
|
||||||
drawSurf->dsFlags = 0;
|
drawSurf->dsFlags = 0;
|
||||||
|
drawSurf->particle_radius = 0.0f; // #3878
|
||||||
|
|
||||||
if ( viewInsideShadow ) {
|
if ( viewInsideShadow ) {
|
||||||
drawSurf->dsFlags |= DSF_VIEW_INSIDE_SHADOW;
|
drawSurf->dsFlags |= DSF_VIEW_INSIDE_SHADOW;
|
||||||
}
|
}
|
||||||
|
@ -1186,7 +1193,8 @@ R_AddDrawSurf
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void R_AddDrawSurf( const srfTriangles_t *tri, const viewEntity_t *space, const renderEntity_t *renderEntity,
|
void R_AddDrawSurf( const srfTriangles_t *tri, const viewEntity_t *space, const renderEntity_t *renderEntity,
|
||||||
const idMaterial *shader, const idScreenRect &scissor ) {
|
const idMaterial *shader, const idScreenRect &scissor, const float soft_particle_radius )
|
||||||
|
{
|
||||||
drawSurf_t *drawSurf;
|
drawSurf_t *drawSurf;
|
||||||
const float *shaderParms;
|
const float *shaderParms;
|
||||||
static float refRegs[MAX_EXPRESSION_REGISTERS]; // don't put on stack, or VC++ will do a page touch
|
static float refRegs[MAX_EXPRESSION_REGISTERS]; // don't put on stack, or VC++ will do a page touch
|
||||||
|
@ -1198,7 +1206,17 @@ void R_AddDrawSurf( const srfTriangles_t *tri, const viewEntity_t *space, const
|
||||||
drawSurf->material = shader;
|
drawSurf->material = shader;
|
||||||
drawSurf->scissorRect = scissor;
|
drawSurf->scissorRect = scissor;
|
||||||
drawSurf->sort = shader->GetSort() + tr.sortOffset;
|
drawSurf->sort = shader->GetSort() + tr.sortOffset;
|
||||||
|
|
||||||
|
if ( soft_particle_radius != -1.0f ) // #3878
|
||||||
|
{
|
||||||
|
drawSurf->dsFlags = DSF_SOFT_PARTICLE;
|
||||||
|
drawSurf->particle_radius = soft_particle_radius;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
drawSurf->dsFlags = 0;
|
drawSurf->dsFlags = 0;
|
||||||
|
drawSurf->particle_radius = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
// bumping this offset each time causes surfaces with equal sort orders to still
|
// bumping this offset each time causes surfaces with equal sort orders to still
|
||||||
// deterministically draw in the order they are added
|
// deterministically draw in the order they are added
|
||||||
|
@ -1218,7 +1236,7 @@ void R_AddDrawSurf( const srfTriangles_t *tri, const viewEntity_t *space, const
|
||||||
}
|
}
|
||||||
tr.viewDef->drawSurfs = (drawSurf_t **)R_FrameAlloc( tr.viewDef->maxDrawSurfs * sizeof( tr.viewDef->drawSurfs[0] ) );
|
tr.viewDef->drawSurfs = (drawSurf_t **)R_FrameAlloc( tr.viewDef->maxDrawSurfs * sizeof( tr.viewDef->drawSurfs[0] ) );
|
||||||
if(count > 0)
|
if(count > 0)
|
||||||
memcpy( tr.viewDef->drawSurfs, old, count ); // XXX null pointer passed as argument 2, which is declared to never be null
|
memcpy( tr.viewDef->drawSurfs, old, count );
|
||||||
}
|
}
|
||||||
tr.viewDef->drawSurfs[tr.viewDef->numDrawSurfs] = drawSurf;
|
tr.viewDef->drawSurfs[tr.viewDef->numDrawSurfs] = drawSurf;
|
||||||
tr.viewDef->numDrawSurfs++;
|
tr.viewDef->numDrawSurfs++;
|
||||||
|
@ -1423,8 +1441,21 @@ static void R_AddAmbientDrawsurfs( viewEntity_t *vEntity ) {
|
||||||
vertexCache.Touch( tri->indexCache );
|
vertexCache.Touch( tri->indexCache );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Soft Particles -- SteveL #3878
|
||||||
|
float particle_radius = -1.0f; // Default = disallow softening, but allow modelDepthHack if specified in the decl.
|
||||||
|
if ( r_useSoftParticles.GetBool()
|
||||||
|
&& !shader->ReceivesLighting() // don't soften surfaces that are meant to be solid
|
||||||
|
&& tr.viewDef->renderView.viewID >= 0 ) // Skip during "invisible" rendering passes (e.g. lightgem)
|
||||||
|
{
|
||||||
|
const idRenderModelPrt* prt = dynamic_cast<const idRenderModelPrt*>( def->parms.hModel ); // yuck.
|
||||||
|
if ( prt )
|
||||||
|
{
|
||||||
|
particle_radius = prt->SofteningRadius( surf->id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add the surface for drawing
|
// add the surface for drawing
|
||||||
R_AddDrawSurf( tri, vEntity, &vEntity->entityDef->parms, shader, vEntity->scissorRect );
|
R_AddDrawSurf( tri, vEntity, &vEntity->entityDef->parms, shader, vEntity->scissorRect, particle_radius );
|
||||||
|
|
||||||
// ambientViewCount is used to allow light interactions to be rejected
|
// ambientViewCount is used to allow light interactions to be rejected
|
||||||
// if the ambient surface isn't visible at all
|
// if the ambient surface isn't visible at all
|
||||||
|
@ -1514,6 +1545,14 @@ void R_AddModelSurfaces( void ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't let particle entities re-instantiate their dynamic model during non-visible
|
||||||
|
// views (in TDM, the light gem render) -- SteveL #3970
|
||||||
|
if ( tr.viewDef->renderView.viewID < 0
|
||||||
|
&& dynamic_cast<const idRenderModelPrt*>( vEntity->entityDef->parms.hModel ) != NULL ) // yuck.
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// add the ambient surface if it has a visible rectangle
|
// add the ambient surface if it has a visible rectangle
|
||||||
if ( !vEntity->scissorRect.IsEmpty() ) {
|
if ( !vEntity->scissorRect.IsEmpty() ) {
|
||||||
model = R_EntityDefDynamicModel( vEntity->entityDef );
|
model = R_EntityDefDynamicModel( vEntity->entityDef );
|
||||||
|
|
|
@ -109,6 +109,7 @@ SURFACES
|
||||||
|
|
||||||
// drawSurf_t are always allocated and freed every frame, they are never cached
|
// drawSurf_t are always allocated and freed every frame, they are never cached
|
||||||
static const int DSF_VIEW_INSIDE_SHADOW = 1;
|
static const int DSF_VIEW_INSIDE_SHADOW = 1;
|
||||||
|
static const int DSF_SOFT_PARTICLE = 2; // #3878 - soft particles
|
||||||
|
|
||||||
typedef struct drawSurf_s {
|
typedef struct drawSurf_s {
|
||||||
const srfTriangles_t *geo;
|
const srfTriangles_t *geo;
|
||||||
|
@ -121,6 +122,7 @@ typedef struct drawSurf_s {
|
||||||
int dsFlags; // DSF_VIEW_INSIDE_SHADOW, etc
|
int dsFlags; // DSF_VIEW_INSIDE_SHADOW, etc
|
||||||
struct vertCache_s *dynamicTexCoords; // float * in vertex cache memory
|
struct vertCache_s *dynamicTexCoords; // float * in vertex cache memory
|
||||||
// specular directions for non vertex program cards, skybox texcoords, etc
|
// specular directions for non vertex program cards, skybox texcoords, etc
|
||||||
|
float particle_radius; // The radius of individual quads for soft particles #3878
|
||||||
} drawSurf_t;
|
} drawSurf_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1179,7 +1181,7 @@ viewEntity_t *R_SetEntityDefViewEntity( idRenderEntityLocal *def );
|
||||||
viewLight_t *R_SetLightDefViewLight( idRenderLightLocal *def );
|
viewLight_t *R_SetLightDefViewLight( idRenderLightLocal *def );
|
||||||
|
|
||||||
void R_AddDrawSurf( const srfTriangles_t *tri, const viewEntity_t *space, const renderEntity_t *renderEntity,
|
void R_AddDrawSurf( const srfTriangles_t *tri, const viewEntity_t *space, const renderEntity_t *renderEntity,
|
||||||
const idMaterial *shader, const idScreenRect &scissor );
|
const idMaterial *shader, const idScreenRect &scissor, const float soft_particle_radius = -1.0f ); // soft particles in #3878
|
||||||
|
|
||||||
void R_LinkLightSurf( const drawSurf_t **link, const srfTriangles_t *tri, const viewEntity_t *space,
|
void R_LinkLightSurf( const drawSurf_t **link, const srfTriangles_t *tri, const viewEntity_t *space,
|
||||||
const idRenderLightLocal *light, const idMaterial *shader, const idScreenRect &scissor, bool viewInsideShadow );
|
const idRenderLightLocal *light, const idMaterial *shader, const idScreenRect &scissor, bool viewInsideShadow );
|
||||||
|
@ -1315,6 +1317,10 @@ typedef enum {
|
||||||
FPROG_AMBIENT,
|
FPROG_AMBIENT,
|
||||||
VPROG_GLASSWARP,
|
VPROG_GLASSWARP,
|
||||||
FPROG_GLASSWARP,
|
FPROG_GLASSWARP,
|
||||||
|
// SteveL #3878: soft particles
|
||||||
|
VPROG_SOFT_PARTICLE,
|
||||||
|
FPROG_SOFT_PARTICLE,
|
||||||
|
//
|
||||||
PROG_USER
|
PROG_USER
|
||||||
} program_t;
|
} program_t;
|
||||||
|
|
||||||
|
@ -1362,9 +1368,22 @@ typedef enum {
|
||||||
PP_SPECULAR_MATRIX_S,
|
PP_SPECULAR_MATRIX_S,
|
||||||
PP_SPECULAR_MATRIX_T,
|
PP_SPECULAR_MATRIX_T,
|
||||||
PP_COLOR_MODULATE,
|
PP_COLOR_MODULATE,
|
||||||
PP_COLOR_ADD,
|
PP_COLOR_ADD, // 17
|
||||||
|
|
||||||
PP_LIGHT_FALLOFF_TQ = 20 // only for NV programs
|
PP_LIGHT_FALLOFF_TQ = 20, // only for NV programs - DG: unused
|
||||||
|
PP_GAMMA_BRIGHTNESS = 21, // DG: for gamma in shader: { r_brightness, r_brightness, r_brightness, 1/r_gamma }
|
||||||
|
// DG: for soft particles from TDM: reciprocal of _currentDepth size.
|
||||||
|
// Lets us convert a screen position to a texcoord in _currentDepth
|
||||||
|
PP_CURDEPTH_RECIPR = 22,
|
||||||
|
// DG: for soft particles from TDM: 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.
|
||||||
|
PP_PARTICLE_RADIUS = 23,
|
||||||
|
// DG: for soft particles from TDM: 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.
|
||||||
|
PP_PARTICLE_COLCHAN_MASK = 24,
|
||||||
} programParameter_t;
|
} programParameter_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue