Added support for a few colorGen_t and alphaGen_t values

This commit is contained in:
OM 2023-05-15 20:14:45 +02:00
parent 7fb4de0c6c
commit 5b141089c3
4 changed files with 263 additions and 93 deletions

View file

@ -231,6 +231,7 @@ typedef struct image_s {
typedef enum {
SS_BAD,
SS_PORTAL, // mirrors, portals, viewscreens
SS_PORTALSKY,
SS_ENVIRONMENT, // sky box
SS_OPAQUE, // opaque
@ -239,8 +240,6 @@ typedef enum {
// in addition to alpha test
SS_BANNER,
SS_FOG,
SS_UNDERWATER, // for items that should be drawn in front of the water plane
SS_BLEND0, // regular transparency and filters
@ -336,10 +335,7 @@ typedef enum {
CGEN_SCOORD,
CGEN_TCOORD,
CGEN_DOT,
CGEN_ONE_MINUS_DOT,
CGEN_LIGHTING_DIFFUSE,
CGEN_FOG, // standard fog
CGEN_CONST // fixed color
CGEN_ONE_MINUS_DOT
} colorGen_t;
typedef enum {
@ -2079,13 +2075,21 @@ void RB_CalcModulateColorsByFog( unsigned char *dstColors );
void RB_CalcModulateAlphasByFog( unsigned char *dstColors );
void RB_CalcModulateRGBAsByFog( unsigned char *dstColors );
void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors );
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors );
void RB_CalcWaveColor(const waveForm_t* wf, unsigned char* dstColors, unsigned char* constantColor);
void RB_CalcAlphaFromEntity( unsigned char *dstColors );
void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors );
void RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords );
void RB_CalcColorFromEntity( unsigned char *dstColors );
void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors );
void RB_CalcSpecularAlpha( unsigned char *alphas );
void RB_CalcColorFromConstant(unsigned char* dstColors, unsigned char* constantColor);
void RB_CalcRGBFromDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcRGBFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcAlphaFromConstant(unsigned char* dstColors, int constantAlpha);
void RB_CalcAlphaFromDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcAlphaFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcAlphaFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st);
void RB_CalcRGBFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st);
void RB_CalcSpecularAlpha(unsigned char* alphas, float alphaMax, vec3_t lightOrigin);
void RB_CalcLightGridColor(unsigned char* colors);
void RB_CalcAlphaFromDotView(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcAlphaFromOneMinusDotView(unsigned char* colors, float alphaMin, float alphaMax);

View file

@ -693,25 +693,37 @@ static void ComputeColors( shaderStage_t *pStage )
case CGEN_IDENTITY_LIGHTING:
Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 );
break;
case CGEN_LIGHTING_DIFFUSE:
RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
case CGEN_ENTITY:
RB_CalcColorFromEntity((unsigned char*)tess.svars.colors);
break;
case CGEN_ONE_MINUS_ENTITY:
RB_CalcColorFromOneMinusEntity((unsigned char*)tess.svars.colors);
break;
case CGEN_EXACT_VERTEX:
Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
if (!tess.vertexColorValid) {
ri.Printf(
PRINT_WARNING,
"Vertex color specified for shader '%s', but vertex colors are not valid for this model\n",
tess.shader->name);
break;
case CGEN_CONST:
for ( i = 0; i < tess.numVertexes; i++ ) {
*(int *)tess.svars.colors[i] = *(int *)pStage->colorConst;
}
Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
break;
case CGEN_VERTEX:
if ( tr.identityLight == 1 )
if (!tess.vertexColorValid) {
ri.Printf(
PRINT_WARNING,
"Vertex color specified for shader '%s', but vertex colors are not valid for this model\n",
tess.shader->name);
break;
}
if (tr.identityLight == 1)
{
Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
Com_Memcpy(tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof(tess.vertexColors[0]));
}
else
{
for ( i = 0; i < tess.numVertexes; i++ )
for (i = 0; i < tess.numVertexes; i++)
{
tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight;
tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight;
@ -740,25 +752,56 @@ static void ComputeColors( shaderStage_t *pStage )
}
}
break;
case CGEN_FOG:
{
fog_t *fog;
fog = tr.world->fogs + tess.fogNum;
for ( i = 0; i < tess.numVertexes; i++ ) {
* ( int * )&tess.svars.colors[i] = fog->colorInt;
}
}
break;
case CGEN_WAVEFORM:
RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors );
RB_CalcWaveColor(&pStage->rgbWave, (unsigned char*)tess.svars.colors, NULL);
break;
case CGEN_ENTITY:
RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors );
case CGEN_MULTIPLY_BY_WAVEFORM:
RB_CalcWaveColor(&pStage->rgbWave, (unsigned char*)tess.svars.colors, pStage->colorConst);
break;
case CGEN_ONE_MINUS_ENTITY:
RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
case CGEN_LIGHTING_GRID:
RB_CalcLightGridColor((unsigned int*)tess.svars.colors);
break;
case CGEN_LIGHTING_SPHERICAL:
case CGEN_STATIC:
if (!r_drawspherelights->integer)
break;
// FIXME: unimplemented
break;
case CGEN_CONSTANT:
RB_CalcColorFromConstant((unsigned char*)tess.svars.colors, pStage->colorConst);
break;
case CGEN_GLOBAL_COLOR:
RB_CalcColorFromConstant((unsigned char*)tess.svars.colors, backEnd.color2D);
break;
case CGEN_SCOORD:
RB_CalcRGBFromTexCoords(
(unsigned char*)tess.svars.colors,
pStage->alphaMin,
pStage->alphaMax,
pStage->alphaConstMin,
pStage->alphaConst,
1.0,
0.0,
tess.svars.texcoords[0][0]
);
break;
case CGEN_TCOORD:
RB_CalcRGBFromTexCoords(
(unsigned char*)tess.svars.colors,
pStage->alphaMin,
pStage->alphaMax,
pStage->alphaConstMin,
pStage->alphaConst,
0.0,
1.0,
tess.svars.texcoords[0][0]
);
break;
case CGEN_DOT:
RB_CalcRGBFromDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax);
break;
case CGEN_ONE_MINUS_DOT:
RB_CalcRGBFromOneMinusDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax);
break;
}
@ -779,38 +822,31 @@ static void ComputeColors( shaderStage_t *pStage )
}
}
break;
case AGEN_CONSTANT:
if ( pStage->rgbGen != CGEN_CONST ) {
for ( i = 0; i < tess.numVertexes; i++ ) {
tess.svars.colors[i][3] = pStage->colorConst[3];
}
}
break;
case AGEN_WAVEFORM:
RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors );
break;
case AGEN_LIGHTING_SPECULAR:
RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors );
break;
case AGEN_ENTITY:
RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors );
RB_CalcAlphaFromEntity((unsigned char*)tess.svars.colors);
break;
case AGEN_ONE_MINUS_ENTITY:
RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
RB_CalcAlphaFromOneMinusEntity((unsigned char*)tess.svars.colors);
break;
case AGEN_VERTEX:
if ( pStage->rgbGen != CGEN_VERTEX ) {
for ( i = 0; i < tess.numVertexes; i++ ) {
if (pStage->rgbGen != CGEN_VERTEX) {
for (i = 0; i < tess.numVertexes; i++) {
tess.svars.colors[i][3] = tess.vertexColors[i][3];
}
}
break;
case AGEN_ONE_MINUS_VERTEX:
for ( i = 0; i < tess.numVertexes; i++ )
for (i = 0; i < tess.numVertexes; i++)
{
tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3];
}
break;
case AGEN_LIGHTING_SPECULAR:
RB_CalcSpecularAlpha((unsigned char*)tess.svars.colors, pStage->alphaMax, pStage->specOrigin);
break;
case AGEN_WAVEFORM:
RB_CalcWaveAlpha(&pStage->alphaWave, (unsigned char*)tess.svars.colors);
break;
case AGEN_PORTAL:
{
unsigned char alpha;
@ -842,6 +878,62 @@ static void ComputeColors( shaderStage_t *pStage )
}
}
break;
case AGEN_DOT:
RB_CalcAlphaFromDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax);
return;
case AGEN_ONE_MINUS_DOT:
RB_CalcAlphaFromOneMinusDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax);
return;
case AGEN_CONSTANT:
RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, pStage->colorConst[3]);
break;
case AGEN_GLOBAL_ALPHA:
RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, backEnd.color2D[3]);
break;
case AGEN_SKYALPHA:
RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, tr.refdef.sky_alpha * 255.0);
break;
case AGEN_ONE_MINUS_SKYALPHA:
RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, (1.0 - tr.refdef.sky_alpha) * 255.0);
break;
case AGEN_SCOORD:
RB_CalcAlphaFromTexCoords(
(unsigned char*)tess.svars.colors,
pStage->alphaMin,
pStage->alphaMax,
pStage->alphaConstMin,
pStage->alphaConst,
1.0,
0.0,
tess.svars.texcoords[0][0]
);
break;
case AGEN_TCOORD:
RB_CalcAlphaFromTexCoords(
(unsigned char*)tess.svars.colors,
pStage->alphaMin,
pStage->alphaMax,
pStage->alphaConstMin,
pStage->alphaConst,
0.0,
1.0,
tess.svars.texcoords[0][0]
);
break;
case AGEN_DIST_FADE:
// FIXME: unimplemented
break;
case AGEN_ONE_MINUS_DIST_FADE:
// FIXME: unimplemented
break;
case AGEN_DOT_VIEW:
RB_CalcAlphaFromDotView((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax);
break;
case AGEN_ONE_MINUS_DOT_VIEW:
RB_CalcAlphaFromOneMinusDotView((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax);
break;
default:
break;
}
}

View file

@ -262,7 +262,7 @@ Change a polygon into a bunch of text polygons
void DeformText( const char *text ) {
int i;
vec3_t origin, width, height;
int len;
size_t len;
int ch;
byte color[4];
float bottom, top;
@ -632,6 +632,60 @@ void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
}
}
/*
** RB_CalcColorFromConstant
*/
void RB_CalcColorFromConstant(unsigned char* dstColors, unsigned char* constantColor)
{
int i;
for (i = 0; i < tess.numVertexes; i++) {
dstColors[i * 4] = constantColor[i * 4];
dstColors[i * 4 + 1] = constantColor[i * 4 + 1];
dstColors[i * 4 + 2] = constantColor[i * 4 + 2];
dstColors[i * 4 + 3] = constantColor[i * 4 + 3];
}
}
void RB_CalcRGBFromDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcRGBFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcAlphaFromConstant(unsigned char* dstColors, int constantAlpha)
{
int i;
for (i = 0; i < tess.numVertexes; i++) {
dstColors[i * 4 + 3] = constantAlpha;
}
}
void RB_CalcAlphaFromDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcAlphaFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcAlphaFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st)
{
// FIXME: unimplemented
}
void RB_CalcRGBFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st)
{
// FIXME: unimplemented
}
/*
** RB_CalcAlphaFromEntity
*/
@ -671,7 +725,7 @@ void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors )
/*
** RB_CalcWaveColor
*/
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
void RB_CalcWaveColor(const waveForm_t* wf, unsigned char* dstColors, unsigned char* constantColor)
{
int i;
int v;
@ -693,10 +747,20 @@ void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
glow = 1;
}
v = myftol( 255 * glow );
if (constantColor)
{
color[0] = constantColor[0] * glow;
color[1] = constantColor[1] * glow;
color[2] = constantColor[2] * glow;
}
else
{
v = myftol(255 * glow);
color[0] = color[1] = color[2] = v;
}
color[3] = 255;
v = *(int *)color;
v = *(int*)color;
for ( i = 0; i < tess.numVertexes; i++, colors++ ) {
*colors = v;
@ -1034,7 +1098,7 @@ long myftol( float f ) {
*/
vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically
void RB_CalcSpecularAlpha( unsigned char *alphas ) {
void RB_CalcSpecularAlpha(unsigned char* alphas, float alphaMax, vec3_t lightOrigin) {
int i;
float *v, *normal;
vec3_t viewer, reflected;

View file

@ -853,7 +853,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
stage->colorConst[1] = 255 * color[1];
stage->colorConst[2] = 255 * color[2];
stage->rgbGen = CGEN_CONST;
stage->rgbGen = CGEN_CONSTANT;
}
else if ( !Q_stricmp( token, "identity" ) )
{
@ -882,9 +882,13 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
{
stage->rgbGen = CGEN_EXACT_VERTEX;
}
else if ( !Q_stricmp( token, "lightingDiffuse" ) )
else if ( !Q_stricmp( token, "lightingGrid" ) )
{
stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
stage->rgbGen = CGEN_LIGHTING_GRID;
}
else if ( !Q_stricmp( token, "lightingSpherical" ) )
{
stage->rgbGen = CGEN_LIGHTING_SPHERICAL;
}
else if ( !Q_stricmp( token, "oneMinusVertex" ) )
{
@ -1084,7 +1088,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
// decide which agens we can skip
if ( stage->alphaGen == CGEN_IDENTITY ) {
if ( stage->rgbGen == CGEN_IDENTITY
|| stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) {
|| stage->rgbGen == CGEN_LIGHTING_GRID
|| stage->rgbGen == CGEN_LIGHTING_SPHERICAL ) {
stage->alphaGen = AGEN_SKIP;
}
}
@ -1695,11 +1700,11 @@ static void ComputeStageIteratorFunc( void )
//
if ( shader.numUnfoggedPasses == 1 )
{
if ( unfoggedStages[0].rgbGen == CGEN_LIGHTING_DIFFUSE )
if ( unfoggedStages[0].rgbGen == CGEN_LIGHTING_GRID || unfoggedStages[0].rgbGen == CGEN_LIGHTING_SPHERICAL )
{
if ( unfoggedStages[0].alphaGen == AGEN_IDENTITY )
if ( unfoggedStages[0].alphaGen == AGEN_IDENTITY || unfoggedStages[0].alphaGen == AGEN_SKIP)
{
if ( unfoggedStages[0].bundle[0].tcGen == TCGEN_TEXTURE )
if ( unfoggedStages[0].bundle[0].tcGen == TCGEN_TEXTURE && unfoggedStages[0].bundle[1].tcGen == TCGEN_LIGHTMAP)
{
if ( !shader.polygonOffset )
{
@ -1722,7 +1727,7 @@ static void ComputeStageIteratorFunc( void )
//
if ( shader.numUnfoggedPasses == 1 )
{
if ( ( unfoggedStages[0].rgbGen == CGEN_IDENTITY ) && ( unfoggedStages[0].alphaGen == AGEN_IDENTITY ) )
if ( ( unfoggedStages[0].rgbGen == CGEN_IDENTITY ) && ( unfoggedStages[0].alphaGen == AGEN_IDENTITY || unfoggedStages[0].alphaGen == AGEN_SKIP ) )
{
if ( unfoggedStages[0].bundle[0].tcGen == TCGEN_TEXTURE &&
unfoggedStages[0].bundle[1].tcGen == TCGEN_LIGHTMAP )
@ -2120,7 +2125,7 @@ static void VertexLightingCollapse( void ) {
unfoggedStages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
unfoggedStages[0].stateBits |= GLS_DEPTHMASK_TRUE;
if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
unfoggedStages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
unfoggedStages[0].rgbGen = CGEN_LIGHTING_GRID;
} else {
unfoggedStages[0].rgbGen = CGEN_EXACT_VERTEX;
}
@ -2203,10 +2208,6 @@ static shader_t *FinishShader( void ) {
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
shaderStage_t *pStage = &unfoggedStages[stage];
if ( !pStage->active ) {
break;
}
// check for a missing texture
if ( !pStage->bundle[0].image[0] ) {
ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name );
@ -2214,6 +2215,12 @@ static shader_t *FinishShader( void ) {
continue;
}
if (pStage->rgbGen == CGEN_LIGHTING_GRID) {
shader.needsLGrid = 1;
} else if (pStage->rgbGen == CGEN_LIGHTING_SPHERICAL || pStage->rgbGen == CGEN_STATIC) {
shader.needsLSpherical = 1;
}
//
// default texture coordinate generation
//
@ -2266,7 +2273,7 @@ static shader_t *FinishShader( void ) {
//
// if we are in r_vertexLight mode, never use a lightmap texture
//
if ( stage > 1 && ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) {
if ( stage > 1 && r_vertexLight->integer ) {
VertexLightingCollapse();
stage = 1;
hasLightmapStage = qfalse;
@ -2275,28 +2282,31 @@ static shader_t *FinishShader( void ) {
//
// look for multitexture potential
//
if ( stage > 1 && CollapseMultitexture() ) {
stage--;
if (stage > 1 && qglActiveTextureARB) {
CollapseMultitexture();
};
// FIXME: fog shader
// fogonly shaders don't have any normal passes
if (stage == 0) {
shader.sort = SS_OPAQUE;
}
if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
if (vertexLightmap) {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name );
} else {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name );
if (shader.lightmapIndex >= 0 && !hasLightmapStage) {
ri.Printf(PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name);
shader.lightmapIndex = LIGHTMAP_NONE;
}
}
//
// compute number of passes
//
shader.numUnfoggedPasses = stage;
// fogonly shaders don't have any normal passes
if ( stage == 0 ) {
shader.sort = SS_FOG;
shader.numUnfoggedPasses = 0;
for (stage = 0; stage < MAX_SHADER_STAGES; stage++) {
shaderStage_t* pStage = &unfoggedStages[stage];
if (pStage->active) {
shader.numUnfoggedPasses++;
}
}
// determine which stage iterator function is appropriate