Finished adding Prey's material tokens.

This commit is contained in:
Justin Marshall
2026-05-05 17:57:38 -07:00
parent d06356e042
commit a51e42f312
2 changed files with 409 additions and 213 deletions
+363 -213
View File
@@ -1149,368 +1149,458 @@ An open brace has been parsed
================= =================
*/ */
void idMaterial::ParseStage( idLexer &src, const textureRepeat_t trpDefault ) { void idMaterial::ParseStage(idLexer& src, const textureRepeat_t trpDefault) {
idToken token; idToken token;
const char *str; const char* str;
shaderStage_t *ss; shaderStage_t* ss;
textureStage_t *ts; textureStage_t* ts;
textureFilter_t tf; textureFilter_t tf;
textureRepeat_t trp; textureRepeat_t trp;
textureDepth_t td; textureDepth_t td;
cubeFiles_t cubeMap; cubeFiles_t cubeMap;
bool allowPicmip; bool allowPicmip;
#ifdef PREY
bool highres;
bool preyTokenOnlyStage;
#endif
char imageName[MAX_IMAGE_NAME]; char imageName[MAX_IMAGE_NAME];
int a, b; int a, b;
int matrix[2][3]; int matrix[2][3];
newShaderStage_t newStage; newShaderStage_t newStage;
if ( numStages >= MAX_SHADER_STAGES ) { if (numStages >= MAX_SHADER_STAGES) {
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
common->Warning( "material '%s' exceeded %i stages", GetName(), MAX_SHADER_STAGES ); common->Warning("material '%s' exceeded %i stages", GetName(), MAX_SHADER_STAGES);
} }
tf = TF_DEFAULT; tf = TF_DEFAULT;
trp = trpDefault; trp = trpDefault;
td = TD_DEFAULT; td = TD_DEFAULT;
allowPicmip = true; allowPicmip = true;
#ifdef PREY
highres = false;
preyTokenOnlyStage = false;
#endif
cubeMap = CF_2D; cubeMap = CF_2D;
imageName[0] = 0; imageName[0] = 0;
memset( &newStage, 0, sizeof( newStage ) ); memset(&newStage, 0, sizeof(newStage));
ss = &pd->parseStages[numStages]; ss = &pd->parseStages[numStages];
ts = &ss->texture; ts = &ss->texture;
ClearStage( ss ); ClearStage(ss);
#ifdef PREY
ss->isGlow = false;
ss->isScopeView = false;
ss->isShuttleView = false;
ss->isNotScopeView = false;
ss->isSpiritWalk = false;
ss->isNotSpiritWalk = false;
ss->specular.exponent = 22.0f;
ss->specular.brightness = 1.4f;
#endif
while ( 1 ) { while (1) {
if ( TestMaterialFlag( MF_DEFAULTED ) ) { // we have a parse error if (TestMaterialFlag(MF_DEFAULTED)) { // we have a parse error
return; return;
} }
if ( !src.ExpectAnyToken( &token ) ) { if (!src.ExpectAnyToken(&token)) {
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
// the close brace for the entire material ends the draw block // the close brace for the entire material ends the draw block
if ( token == "}" ) { if (token == "}") {
break; break;
} }
//BSM Nerve: Added for stage naming in the material editor //BSM Nerve: Added for stage naming in the material editor
if( !token.Icmp( "name") ) { if (!token.Icmp("name")) {
src.SkipRestOfLine(); src.SkipRestOfLine();
continue; continue;
} }
// image options // image options
if ( !token.Icmp( "blend" ) ) { if (!token.Icmp("blend")) {
ParseBlend( src, ss ); ParseBlend(src, ss);
continue; continue;
} }
if ( !token.Icmp( "map" ) ) { if (!token.Icmp("map")) {
str = R_ParsePastImageProgram( src ); str = R_ParsePastImageProgram(src);
idStr::Copynz( imageName, str, sizeof( imageName ) ); idStr::Copynz(imageName, str, sizeof(imageName));
continue; continue;
} }
if ( !token.Icmp( "remoteRenderMap" ) ) { if (!token.Icmp("remoteRenderMap")) {
ts->dynamic = DI_REMOTE_RENDER; ts->dynamic = DI_REMOTE_RENDER;
ts->width = src.ParseInt(); ts->width = src.ParseInt();
ts->height = src.ParseInt(); ts->height = src.ParseInt();
continue; continue;
} }
if ( !token.Icmp( "mirrorRenderMap" ) ) { if (!token.Icmp("mirrorRenderMap")) {
ts->dynamic = DI_MIRROR_RENDER; ts->dynamic = DI_MIRROR_RENDER;
ts->width = src.ParseInt(); ts->width = src.ParseInt();
ts->height = src.ParseInt(); ts->height = src.ParseInt();
ts->texgen = TG_SCREEN; ts->texgen = TG_SCREEN;
continue; continue;
} }
#ifdef PREY
if (!token.Icmp("portalRenderMap")) {
ts->dynamic = DI_PORTAL_RENDER;
ts->width = src.ParseInt();
ts->height = src.ParseInt();
ts->texgen = TG_SCREEN;
continue;
}
if (!token.Icmp("skyboxRenderMap")) {
ts->dynamic = DI_SKYBOX_RENDER;
ts->width = src.ParseInt();
ts->height = src.ParseInt();
ts->texgen = TG_SCREEN;
continue;
}
#endif
if ( !token.Icmp( "xrayRenderMap" ) ) { if (!token.Icmp("xrayRenderMap")) {
ts->dynamic = DI_XRAY_RENDER; ts->dynamic = DI_XRAY_RENDER;
ts->width = src.ParseInt(); ts->width = src.ParseInt();
ts->height = src.ParseInt(); ts->height = src.ParseInt();
ts->texgen = TG_SCREEN; ts->texgen = TG_SCREEN;
continue; continue;
} }
if ( !token.Icmp( "screen" ) ) { if (!token.Icmp("screen")) {
ts->texgen = TG_SCREEN; ts->texgen = TG_SCREEN;
continue; continue;
} }
if ( !token.Icmp( "screen2" ) ) { if (!token.Icmp("screen2")) {
ts->texgen = TG_SCREEN2; ts->texgen = TG_SCREEN2;
continue; continue;
} }
if ( !token.Icmp( "glassWarp" ) ) { if (!token.Icmp("glassWarp")) {
ts->texgen = TG_GLASSWARP; ts->texgen = TG_GLASSWARP;
continue; continue;
} }
if ( !token.Icmp( "videomap" ) ) { if (!token.Icmp("videomap")) {
// note that videomaps will always be in clamp mode, so texture // note that videomaps will always be in clamp mode, so texture
// coordinates had better be in the 0 to 1 range // coordinates had better be in the 0 to 1 range
if ( !src.ReadToken( &token ) ) { if (!src.ReadToken(&token)) {
common->Warning( "missing parameter for 'videoMap' keyword in material '%s'", GetName() ); common->Warning("missing parameter for 'videoMap' keyword in material '%s'", GetName());
continue; continue;
} }
bool loop = false; bool loop = false;
if ( !token.Icmp( "loop" ) ) { if (!token.Icmp("loop")) {
loop = true; loop = true;
if ( !src.ReadToken( &token ) ) { if (!src.ReadToken(&token)) {
common->Warning( "missing parameter for 'videoMap' keyword in material '%s'", GetName() ); common->Warning("missing parameter for 'videoMap' keyword in material '%s'", GetName());
continue; continue;
} }
} }
ts->cinematic = idCinematic::Alloc(); ts->cinematic = idCinematic::Alloc();
ts->cinematic->InitFromFile( token.c_str(), loop ); ts->cinematic->InitFromFile(token.c_str(), loop);
continue; continue;
} }
if ( !token.Icmp( "soundmap" ) ) { if (!token.Icmp("soundmap")) {
if ( !src.ReadToken( &token ) ) { if (!src.ReadToken(&token)) {
common->Warning( "missing parameter for 'soundmap' keyword in material '%s'", GetName() ); common->Warning("missing parameter for 'soundmap' keyword in material '%s'", GetName());
continue; continue;
} }
ts->cinematic = new idSndWindow(); ts->cinematic = new idSndWindow();
ts->cinematic->InitFromFile( token.c_str(), true ); ts->cinematic->InitFromFile(token.c_str(), true);
continue; continue;
} }
#ifdef PREY
if (!token.Icmp("profilemap")) {
if (!src.ReadToken(&token)) {
common->Warning("missing parameter for 'profilemap' keyword in material '%s'", GetName());
continue;
}
// Prey creates an hhProfilerGraph cinematic here. Consume the token so
// retail Prey materials parse even in builds without that runtime class.
preyTokenOnlyStage = true;
continue;
}
#endif
if ( !token.Icmp( "cubeMap" ) ) { if (!token.Icmp("cubeMap")) {
str = R_ParsePastImageProgram( src ); str = R_ParsePastImageProgram(src);
idStr::Copynz( imageName, str, sizeof( imageName ) ); idStr::Copynz(imageName, str, sizeof(imageName));
cubeMap = CF_NATIVE; cubeMap = CF_NATIVE;
continue; continue;
} }
if ( !token.Icmp( "cameraCubeMap" ) ) { if (!token.Icmp("cameraCubeMap")) {
str = R_ParsePastImageProgram( src ); str = R_ParsePastImageProgram(src);
idStr::Copynz( imageName, str, sizeof( imageName ) ); idStr::Copynz(imageName, str, sizeof(imageName));
cubeMap = CF_CAMERA; cubeMap = CF_CAMERA;
continue; continue;
} }
if ( !token.Icmp( "ignoreAlphaTest" ) ) { if (!token.Icmp("ignoreAlphaTest")) {
ss->ignoreAlphaTest = true; ss->ignoreAlphaTest = true;
continue; continue;
} }
if ( !token.Icmp( "nearest" ) ) { if (!token.Icmp("nearest")) {
tf = TF_NEAREST; tf = TF_NEAREST;
continue; continue;
} }
if ( !token.Icmp( "linear" ) ) { if (!token.Icmp("linear")) {
tf = TF_LINEAR; tf = TF_LINEAR;
continue; continue;
} }
if ( !token.Icmp( "clamp" ) ) { if (!token.Icmp("clamp")) {
trp = TR_CLAMP; trp = TR_CLAMP;
continue; continue;
} }
if ( !token.Icmp( "noclamp" ) ) { if (!token.Icmp("noclamp")) {
trp = TR_REPEAT; trp = TR_REPEAT;
continue; continue;
} }
if ( !token.Icmp( "zeroclamp" ) ) { if (!token.Icmp("zeroclamp")) {
trp = TR_CLAMP_TO_ZERO; trp = TR_CLAMP_TO_ZERO;
continue; continue;
} }
if ( !token.Icmp( "alphazeroclamp" ) ) { if (!token.Icmp("alphazeroclamp")) {
trp = TR_CLAMP_TO_ZERO_ALPHA; trp = TR_CLAMP_TO_ZERO_ALPHA;
continue; continue;
} }
if ( !token.Icmp( "uncompressed" ) || !token.Icmp( "highquality" ) ) { if (!token.Icmp("uncompressed") || !token.Icmp("highquality")) {
if ( !globalImages->image_ignoreHighQuality.GetInteger() ) { if (!globalImages->image_ignoreHighQuality.GetInteger()) {
td = TD_HIGH_QUALITY; td = TD_HIGH_QUALITY;
} }
continue; continue;
} }
if ( !token.Icmp( "forceHighQuality" ) ) { if (!token.Icmp("forceHighQuality")) {
td = TD_HIGH_QUALITY; td = TD_HIGH_QUALITY;
continue; continue;
} }
if ( !token.Icmp( "nopicmip" ) ) { if (!token.Icmp("nopicmip")) {
allowPicmip = false; allowPicmip = false;
continue; continue;
} }
if ( !token.Icmp( "vertexColor" ) ) { #ifdef PREY
if (!token.Icmp("highres")) {
// The Hex-Rays build records this and passes it to Prey's image manager.
// This Doom 3-side patch only needs to accept the token safely.
highres = true;
continue;
}
#endif
if (!token.Icmp("vertexColor")) {
ss->vertexColor = SVC_MODULATE; ss->vertexColor = SVC_MODULATE;
continue; continue;
} }
if ( !token.Icmp( "inverseVertexColor" ) ) { if (!token.Icmp("inverseVertexColor")) {
ss->vertexColor = SVC_INVERSE_MODULATE; ss->vertexColor = SVC_INVERSE_MODULATE;
continue; continue;
} }
// privatePolygonOffset // privatePolygonOffset
else if ( !token.Icmp( "privatePolygonOffset" ) ) { else if (!token.Icmp("privatePolygonOffset")) {
if ( !src.ReadTokenOnLine( &token ) ) { if (!src.ReadTokenOnLine(&token)) {
ss->privatePolygonOffset = 1; ss->privatePolygonOffset = 1;
continue; continue;
} }
// explict larger (or negative) offset // explict larger (or negative) offset
src.UnreadToken( &token ); src.UnreadToken(&token);
ss->privatePolygonOffset = src.ParseFloat(); ss->privatePolygonOffset = src.ParseFloat();
continue; continue;
} }
#ifdef PREY
if (!token.Icmp("glowStage")) {
ss->isGlow = true;
continue;
}
if (!token.Icmp("scopeView")) {
ss->isScopeView = true;
continue;
}
if (!token.Icmp("shuttleView")) {
ss->isShuttleView = true;
continue;
}
if (!token.Icmp("notScopeView")) {
ss->isNotScopeView = true;
continue;
}
if (!token.Icmp("spiritWalk")) {
ss->isSpiritWalk = true;
continue;
}
if (!token.Icmp("notSpiritWalk")) {
ss->isNotSpiritWalk = true;
continue;
}
#endif
// texture coordinate generation // texture coordinate generation
if ( !token.Icmp( "texGen" ) ) { if (!token.Icmp("texGen")) {
src.ExpectAnyToken( &token ); src.ExpectAnyToken(&token);
if ( !token.Icmp( "normal" ) ) { if (!token.Icmp("normal")) {
ts->texgen = TG_DIFFUSE_CUBE; ts->texgen = TG_DIFFUSE_CUBE;
} else if ( !token.Icmp( "reflect" ) ) { }
else if (!token.Icmp("reflect")) {
ts->texgen = TG_REFLECT_CUBE; ts->texgen = TG_REFLECT_CUBE;
} else if ( !token.Icmp( "skybox" ) ) { }
else if (!token.Icmp("skybox")) {
ts->texgen = TG_SKYBOX_CUBE; ts->texgen = TG_SKYBOX_CUBE;
} else if ( !token.Icmp( "wobbleSky" ) ) { }
else if (!token.Icmp("wobbleSky")) {
ts->texgen = TG_WOBBLESKY_CUBE; ts->texgen = TG_WOBBLESKY_CUBE;
texGenRegisters[0] = ParseExpression( src ); texGenRegisters[0] = ParseExpression(src);
texGenRegisters[1] = ParseExpression( src ); texGenRegisters[1] = ParseExpression(src);
texGenRegisters[2] = ParseExpression( src ); texGenRegisters[2] = ParseExpression(src);
} else { #ifdef PREY
common->Warning( "bad texGen '%s' in material %s", token.c_str(), GetName() ); }
SetMaterialFlag( MF_DEFAULTED ); else if (!token.Icmp("screen")) {
ts->texgen = TG_SCREEN;
#endif
}
else {
common->Warning("bad texGen '%s' in material %s", token.c_str(), GetName());
SetMaterialFlag(MF_DEFAULTED);
} }
continue; continue;
} }
if ( !token.Icmp( "scroll" ) || !token.Icmp( "translate" ) ) { if (!token.Icmp("scroll") || !token.Icmp("translate")) {
a = ParseExpression( src ); a = ParseExpression(src);
MatchToken( src, "," ); MatchToken(src, ",");
b = ParseExpression( src ); b = ParseExpression(src);
matrix[0][0] = GetExpressionConstant( 1 ); matrix[0][0] = GetExpressionConstant(1);
matrix[0][1] = GetExpressionConstant( 0 ); matrix[0][1] = GetExpressionConstant(0);
matrix[0][2] = a; matrix[0][2] = a;
matrix[1][0] = GetExpressionConstant( 0 ); matrix[1][0] = GetExpressionConstant(0);
matrix[1][1] = GetExpressionConstant( 1 ); matrix[1][1] = GetExpressionConstant(1);
matrix[1][2] = b; matrix[1][2] = b;
MultiplyTextureMatrix( ts, matrix ); MultiplyTextureMatrix(ts, matrix);
continue; continue;
} }
if ( !token.Icmp( "scale" ) ) { if (!token.Icmp("scale")) {
a = ParseExpression( src ); a = ParseExpression(src);
MatchToken( src, "," ); MatchToken(src, ",");
b = ParseExpression( src ); b = ParseExpression(src);
// this just scales without a centering // this just scales without a centering
matrix[0][0] = a; matrix[0][0] = a;
matrix[0][1] = GetExpressionConstant( 0 ); matrix[0][1] = GetExpressionConstant(0);
matrix[0][2] = GetExpressionConstant( 0 ); matrix[0][2] = GetExpressionConstant(0);
matrix[1][0] = GetExpressionConstant( 0 ); matrix[1][0] = GetExpressionConstant(0);
matrix[1][1] = b; matrix[1][1] = b;
matrix[1][2] = GetExpressionConstant( 0 ); matrix[1][2] = GetExpressionConstant(0);
MultiplyTextureMatrix( ts, matrix ); MultiplyTextureMatrix(ts, matrix);
continue; continue;
} }
if ( !token.Icmp( "centerScale" ) ) { if (!token.Icmp("centerScale")) {
a = ParseExpression( src ); a = ParseExpression(src);
MatchToken( src, "," ); MatchToken(src, ",");
b = ParseExpression( src ); b = ParseExpression(src);
// this subtracts 0.5, then scales, then adds 0.5 // this subtracts 0.5, then scales, then adds 0.5
matrix[0][0] = a; matrix[0][0] = a;
matrix[0][1] = GetExpressionConstant( 0 ); matrix[0][1] = GetExpressionConstant(0);
matrix[0][2] = EmitOp( GetExpressionConstant( 0.5 ), EmitOp( GetExpressionConstant( 0.5 ), a, OP_TYPE_MULTIPLY ), OP_TYPE_SUBTRACT ); matrix[0][2] = EmitOp(GetExpressionConstant(0.5), EmitOp(GetExpressionConstant(0.5), a, OP_TYPE_MULTIPLY), OP_TYPE_SUBTRACT);
matrix[1][0] = GetExpressionConstant( 0 ); matrix[1][0] = GetExpressionConstant(0);
matrix[1][1] = b; matrix[1][1] = b;
matrix[1][2] = EmitOp( GetExpressionConstant( 0.5 ), EmitOp( GetExpressionConstant( 0.5 ), b, OP_TYPE_MULTIPLY ), OP_TYPE_SUBTRACT ); matrix[1][2] = EmitOp(GetExpressionConstant(0.5), EmitOp(GetExpressionConstant(0.5), b, OP_TYPE_MULTIPLY), OP_TYPE_SUBTRACT);
MultiplyTextureMatrix( ts, matrix ); MultiplyTextureMatrix(ts, matrix);
continue; continue;
} }
if ( !token.Icmp( "shear" ) ) { if (!token.Icmp("shear")) {
a = ParseExpression( src ); a = ParseExpression(src);
MatchToken( src, "," ); MatchToken(src, ",");
b = ParseExpression( src ); b = ParseExpression(src);
// this subtracts 0.5, then shears, then adds 0.5 // this subtracts 0.5, then shears, then adds 0.5
matrix[0][0] = GetExpressionConstant( 1 ); matrix[0][0] = GetExpressionConstant(1);
matrix[0][1] = a; matrix[0][1] = a;
matrix[0][2] = EmitOp( GetExpressionConstant( -0.5 ), a, OP_TYPE_MULTIPLY ); matrix[0][2] = EmitOp(GetExpressionConstant(-0.5), a, OP_TYPE_MULTIPLY);
matrix[1][0] = b; matrix[1][0] = b;
matrix[1][1] = GetExpressionConstant( 1 ); matrix[1][1] = GetExpressionConstant(1);
matrix[1][2] = EmitOp( GetExpressionConstant( -0.5 ), b, OP_TYPE_MULTIPLY ); matrix[1][2] = EmitOp(GetExpressionConstant(-0.5), b, OP_TYPE_MULTIPLY);
MultiplyTextureMatrix( ts, matrix ); MultiplyTextureMatrix(ts, matrix);
continue; continue;
} }
if ( !token.Icmp( "rotate" ) ) { if (!token.Icmp("rotate")) {
const idDeclTable *table; const idDeclTable* table;
int sinReg, cosReg; int sinReg, cosReg;
// in cycles // in cycles
a = ParseExpression( src ); a = ParseExpression(src);
table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, "sinTable", false ) ); table = static_cast<const idDeclTable*>(declManager->FindType(DECL_TABLE, "sinTable", false));
if ( !table ) { if (!table) {
common->Warning( "no sinTable for rotate defined" ); common->Warning("no sinTable for rotate defined");
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
sinReg = EmitOp( table->Index(), a, OP_TYPE_TABLE ); sinReg = EmitOp(table->Index(), a, OP_TYPE_TABLE);
table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, "cosTable", false ) ); table = static_cast<const idDeclTable*>(declManager->FindType(DECL_TABLE, "cosTable", false));
if ( !table ) { if (!table) {
common->Warning( "no cosTable for rotate defined" ); common->Warning("no cosTable for rotate defined");
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
cosReg = EmitOp( table->Index(), a, OP_TYPE_TABLE ); cosReg = EmitOp(table->Index(), a, OP_TYPE_TABLE);
// this subtracts 0.5, then rotates, then adds 0.5 // this subtracts 0.5, then rotates, then adds 0.5
matrix[0][0] = cosReg; matrix[0][0] = cosReg;
matrix[0][1] = EmitOp( GetExpressionConstant( 0 ), sinReg, OP_TYPE_SUBTRACT ); matrix[0][1] = EmitOp(GetExpressionConstant(0), sinReg, OP_TYPE_SUBTRACT);
matrix[0][2] = EmitOp( EmitOp( EmitOp( GetExpressionConstant( -0.5 ), cosReg, OP_TYPE_MULTIPLY ), matrix[0][2] = EmitOp(EmitOp(EmitOp(GetExpressionConstant(-0.5), cosReg, OP_TYPE_MULTIPLY),
EmitOp( GetExpressionConstant( 0.5 ), sinReg, OP_TYPE_MULTIPLY ), OP_TYPE_ADD ), EmitOp(GetExpressionConstant(0.5), sinReg, OP_TYPE_MULTIPLY), OP_TYPE_ADD),
GetExpressionConstant( 0.5 ), OP_TYPE_ADD ); GetExpressionConstant(0.5), OP_TYPE_ADD);
matrix[1][0] = sinReg; matrix[1][0] = sinReg;
matrix[1][1] = cosReg; matrix[1][1] = cosReg;
matrix[1][2] = EmitOp( EmitOp( EmitOp( GetExpressionConstant( -0.5 ), sinReg, OP_TYPE_MULTIPLY ), matrix[1][2] = EmitOp(EmitOp(EmitOp(GetExpressionConstant(-0.5), sinReg, OP_TYPE_MULTIPLY),
EmitOp( GetExpressionConstant( -0.5 ), cosReg, OP_TYPE_MULTIPLY ), OP_TYPE_ADD ), EmitOp(GetExpressionConstant(-0.5), cosReg, OP_TYPE_MULTIPLY), OP_TYPE_ADD),
GetExpressionConstant( 0.5 ), OP_TYPE_ADD ); GetExpressionConstant(0.5), OP_TYPE_ADD);
MultiplyTextureMatrix( ts, matrix ); MultiplyTextureMatrix(ts, matrix);
continue; continue;
} }
// color mask options // color mask options
if ( !token.Icmp( "maskRed" ) ) { if (!token.Icmp("maskRed")) {
ss->drawStateBits |= GLS_REDMASK; ss->drawStateBits |= GLS_REDMASK;
continue; continue;
} }
if ( !token.Icmp( "maskGreen" ) ) { if (!token.Icmp("maskGreen")) {
ss->drawStateBits |= GLS_GREENMASK; ss->drawStateBits |= GLS_GREENMASK;
continue; continue;
} }
if ( !token.Icmp( "maskBlue" ) ) { if (!token.Icmp("maskBlue")) {
ss->drawStateBits |= GLS_BLUEMASK; ss->drawStateBits |= GLS_BLUEMASK;
continue; continue;
} }
if ( !token.Icmp( "maskAlpha" ) ) { if (!token.Icmp("maskAlpha")) {
ss->drawStateBits |= GLS_ALPHAMASK; ss->drawStateBits |= GLS_ALPHAMASK;
continue; continue;
} }
if ( !token.Icmp( "maskColor" ) ) { if (!token.Icmp("maskColor")) {
ss->drawStateBits |= GLS_COLORMASK; ss->drawStateBits |= GLS_COLORMASK;
continue; continue;
} }
if ( !token.Icmp( "maskDepth" ) ) { if (!token.Icmp("maskDepth")) {
ss->drawStateBits |= GLS_DEPTHMASK; ss->drawStateBits |= GLS_DEPTHMASK;
continue; continue;
} }
if ( !token.Icmp( "alphaTest" ) ) { if (!token.Icmp("alphaTest")) {
ss->hasAlphaTest = true; ss->hasAlphaTest = true;
ss->alphaTestRegister = ParseExpression( src ); ss->alphaTestRegister = ParseExpression(src);
coverage = MC_PERFORATED; coverage = MC_PERFORATED;
continue; continue;
} }
// shorthand for 2D modulated // shorthand for 2D modulated
if ( !token.Icmp( "colored" ) ) { if (!token.Icmp("colored")) {
ss->color.registers[0] = EXP_REG_PARM0; ss->color.registers[0] = EXP_REG_PARM0;
ss->color.registers[1] = EXP_REG_PARM1; ss->color.registers[1] = EXP_REG_PARM1;
ss->color.registers[2] = EXP_REG_PARM2; ss->color.registers[2] = EXP_REG_PARM2;
@@ -1519,58 +1609,110 @@ void idMaterial::ParseStage( idLexer &src, const textureRepeat_t trpDefault ) {
continue; continue;
} }
if ( !token.Icmp( "color" ) ) { if (!token.Icmp("color")) {
ss->color.registers[0] = ParseExpression( src ); ss->color.registers[0] = ParseExpression(src);
MatchToken( src, "," ); MatchToken(src, ",");
ss->color.registers[1] = ParseExpression( src ); ss->color.registers[1] = ParseExpression(src);
MatchToken( src, "," ); MatchToken(src, ",");
ss->color.registers[2] = ParseExpression( src ); ss->color.registers[2] = ParseExpression(src);
MatchToken( src, "," ); MatchToken(src, ",");
ss->color.registers[3] = ParseExpression( src ); ss->color.registers[3] = ParseExpression(src);
continue; continue;
} }
if ( !token.Icmp( "red" ) ) { if (!token.Icmp("red")) {
ss->color.registers[0] = ParseExpression( src ); ss->color.registers[0] = ParseExpression(src);
continue; continue;
} }
if ( !token.Icmp( "green" ) ) { if (!token.Icmp("green")) {
ss->color.registers[1] = ParseExpression( src ); ss->color.registers[1] = ParseExpression(src);
continue; continue;
} }
if ( !token.Icmp( "blue" ) ) { if (!token.Icmp("blue")) {
ss->color.registers[2] = ParseExpression( src ); ss->color.registers[2] = ParseExpression(src);
continue; continue;
} }
if ( !token.Icmp( "alpha" ) ) { if (!token.Icmp("alpha")) {
ss->color.registers[3] = ParseExpression( src ); ss->color.registers[3] = ParseExpression(src);
continue; continue;
} }
if ( !token.Icmp( "rgb" ) ) { if (!token.Icmp("rgb")) {
ss->color.registers[0] = ss->color.registers[1] = ss->color.registers[0] = ss->color.registers[1] =
ss->color.registers[2] = ParseExpression( src ); ss->color.registers[2] = ParseExpression(src);
continue; continue;
} }
if ( !token.Icmp( "rgba" ) ) { if (!token.Icmp("rgba")) {
ss->color.registers[0] = ss->color.registers[1] = ss->color.registers[0] = ss->color.registers[1] =
ss->color.registers[2] = ss->color.registers[3] = ParseExpression( src ); ss->color.registers[2] = ss->color.registers[3] = ParseExpression(src);
continue;
}
#ifdef PREY
if (!token.Icmp("specularExp")) {
ss->specular.exponent = src.ParseFloat();
MatchToken(src, ",");
ss->specular.brightness = src.ParseFloat();
continue;
}
#endif
if (!token.Icmp("if")) {
ss->conditionRegister = ParseExpression(src);
continue; continue;
} }
if ( !token.Icmp( "if" ) ) { #ifdef PREY
ss->conditionRegister = ParseExpression( src ); if (!token.Icmp("program")) {
if (!src.ReadTokenOnLine(&token)) {
common->Warning("missing parameter for 'program' keyword in material '%s'", GetName());
}
preyTokenOnlyStage = true;
continue;
}
if (!token.Icmp("fragmentProgram")) {
if (!src.ReadTokenOnLine(&token)) {
common->Warning("missing parameter for 'fragmentProgram' keyword in material '%s'", GetName());
}
preyTokenOnlyStage = true;
continue;
}
if (!token.Icmp("vertexProgram")) {
if (!src.ReadTokenOnLine(&token)) {
common->Warning("missing parameter for 'vertexProgram' keyword in material '%s'", GetName());
}
preyTokenOnlyStage = true;
continue;
}
if (!token.Icmp("megaTexture")) {
// Full Prey allocates idMegaTexture and binds megaTexture.vfp.
// Keep this parser-only path dependency-free.
if (!src.ReadTokenOnLine(&token)) {
common->Warning("missing parameter for 'megaTexture' keyword in material '%s'", GetName());
}
preyTokenOnlyStage = true;
continue;
}
if (!token.Icmp("vertexParm") || !token.Icmp("fragmentParm") || !token.Icmp("fragmentMap")) {
// These are all single-line shader-program directives in the dump.
src.SkipRestOfLine();
preyTokenOnlyStage = true;
continue; continue;
} }
if (!token.Icmp("shaderLevel1") || !token.Icmp("shaderLevel2") || !token.Icmp("shaderLevel3") ||
!token.Icmp("shaderFallback1") || !token.Icmp("shaderFallback2") || !token.Icmp("shaderFallback3")) {
preyTokenOnlyStage = true;
continue;
}
#endif
common->Warning( "unknown token '%s' in material '%s'", token.c_str(), GetName() ); common->Warning("unknown token '%s' in material '%s'", token.c_str(), GetName());
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
// if we are using newStage, allocate a copy of it // if we are using newStage, allocate a copy of it
if ( newStage.fragmentProgram || newStage.vertexProgram ) { if (newStage.fragmentProgram || newStage.vertexProgram) {
ss->newStage = (newShaderStage_t *)Mem_Alloc( sizeof( newStage ) ); ss->newStage = (newShaderStage_t*)Mem_Alloc(sizeof(newStage));
*(ss->newStage) = newStage; *(ss->newStage) = newStage;
} }
@@ -1578,8 +1720,8 @@ void idMaterial::ParseStage( idLexer &src, const textureRepeat_t trpDefault ) {
numStages++; numStages++;
// select a compressed depth based on what the stage is // select a compressed depth based on what the stage is
if ( td == TD_DEFAULT ) { if (td == TD_DEFAULT) {
switch( ss->lighting ) { switch (ss->lighting) {
case SL_BUMP: case SL_BUMP:
td = TD_BUMP; td = TD_BUMP;
break; break;
@@ -1595,13 +1737,21 @@ void idMaterial::ParseStage( idLexer &src, const textureRepeat_t trpDefault ) {
} }
// now load the image with all the parms we parsed // now load the image with all the parms we parsed
if ( imageName[0] ) { #ifdef PREY
ts->image = globalImages->ImageFromFile( imageName, tf, allowPicmip, trp, td, cubeMap ); (void)highres; // parsed for Prey material compatibility; Doom 3 ImageFromFile has no highres arg.
if ( !ts->image ) { #endif
if (imageName[0]) {
ts->image = globalImages->ImageFromFile(imageName, tf, allowPicmip, trp, td, cubeMap);
if (!ts->image) {
ts->image = globalImages->defaultImage; ts->image = globalImages->defaultImage;
} }
} else if ( !ts->cinematic && !ts->dynamic && !ss->newStage ) { }
common->Warning( "material '%s' had stage with no image", GetName() ); else if (!ts->cinematic && !ts->dynamic && !ss->newStage
#ifdef PREY
&& !preyTokenOnlyStage
#endif
) {
common->Warning("material '%s' had stage with no image", GetName());
ts->image = globalImages->defaultImage; ts->image = globalImages->defaultImage;
} }
} }
@@ -1611,83 +1761,83 @@ void idMaterial::ParseStage( idLexer &src, const textureRepeat_t trpDefault ) {
idMaterial::ParseDeform idMaterial::ParseDeform
=============== ===============
*/ */
void idMaterial::ParseDeform( idLexer &src ) { void idMaterial::ParseDeform(idLexer& src) {
idToken token; idToken token;
if ( !src.ExpectAnyToken( &token ) ) { if (!src.ExpectAnyToken(&token)) {
return; return;
} }
if ( !token.Icmp( "sprite" ) ) { if (!token.Icmp("sprite")) {
deform = DFRM_SPRITE; deform = DFRM_SPRITE;
cullType = CT_TWO_SIDED; cullType = CT_TWO_SIDED;
SetMaterialFlag( MF_NOSHADOWS ); SetMaterialFlag(MF_NOSHADOWS);
return; return;
} }
if ( !token.Icmp( "tube" ) ) { if (!token.Icmp("tube")) {
deform = DFRM_TUBE; deform = DFRM_TUBE;
cullType = CT_TWO_SIDED; cullType = CT_TWO_SIDED;
SetMaterialFlag( MF_NOSHADOWS ); SetMaterialFlag(MF_NOSHADOWS);
return; return;
} }
if ( !token.Icmp( "flare" ) ) { if (!token.Icmp("flare")) {
deform = DFRM_FLARE; deform = DFRM_FLARE;
cullType = CT_TWO_SIDED; cullType = CT_TWO_SIDED;
deformRegisters[0] = ParseExpression( src ); deformRegisters[0] = ParseExpression(src);
SetMaterialFlag( MF_NOSHADOWS ); SetMaterialFlag(MF_NOSHADOWS);
return; return;
} }
if ( !token.Icmp( "expand" ) ) { if (!token.Icmp("expand")) {
deform = DFRM_EXPAND; deform = DFRM_EXPAND;
deformRegisters[0] = ParseExpression( src ); deformRegisters[0] = ParseExpression(src);
return; return;
} }
if ( !token.Icmp( "move" ) ) { if (!token.Icmp("move")) {
deform = DFRM_MOVE; deform = DFRM_MOVE;
deformRegisters[0] = ParseExpression( src ); deformRegisters[0] = ParseExpression(src);
return; return;
} }
if ( !token.Icmp( "turbulent" ) ) { if (!token.Icmp("turbulent")) {
deform = DFRM_TURB; deform = DFRM_TURB;
if ( !src.ExpectAnyToken( &token ) ) { if (!src.ExpectAnyToken(&token)) {
src.Warning( "deform particle missing particle name" ); src.Warning("deform particle missing particle name");
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
deformDecl = declManager->FindType( DECL_TABLE, token.c_str(), true ); deformDecl = declManager->FindType(DECL_TABLE, token.c_str(), true);
deformRegisters[0] = ParseExpression( src ); deformRegisters[0] = ParseExpression(src);
deformRegisters[1] = ParseExpression( src ); deformRegisters[1] = ParseExpression(src);
deformRegisters[2] = ParseExpression( src ); deformRegisters[2] = ParseExpression(src);
return; return;
} }
if ( !token.Icmp( "eyeBall" ) ) { if (!token.Icmp("eyeBall")) {
deform = DFRM_EYEBALL; deform = DFRM_EYEBALL;
return; return;
} }
if ( !token.Icmp( "particle" ) ) { if (!token.Icmp("particle")) {
deform = DFRM_PARTICLE; deform = DFRM_PARTICLE;
if ( !src.ExpectAnyToken( &token ) ) { if (!src.ExpectAnyToken(&token)) {
src.Warning( "deform particle missing particle name" ); src.Warning("deform particle missing particle name");
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
deformDecl = declManager->FindType( DECL_PARTICLE, token.c_str(), true ); deformDecl = declManager->FindType(DECL_PARTICLE, token.c_str(), true);
return; return;
} }
if ( !token.Icmp( "particle2" ) ) { if (!token.Icmp("particle2")) {
deform = DFRM_PARTICLE2; deform = DFRM_PARTICLE2;
if ( !src.ExpectAnyToken( &token ) ) { if (!src.ExpectAnyToken(&token)) {
src.Warning( "deform particle missing particle name" ); src.Warning("deform particle missing particle name");
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
deformDecl = declManager->FindType( DECL_PARTICLE, token.c_str(), true ); deformDecl = declManager->FindType(DECL_PARTICLE, token.c_str(), true);
return; return;
} }
src.Warning( "Bad deform type '%s'", token.c_str() ); src.Warning("Bad deform type '%s'", token.c_str());
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
} }
/* /*
+46
View File
@@ -95,6 +95,10 @@ typedef enum {
DI_CUBE_RENDER, DI_CUBE_RENDER,
DI_MIRROR_RENDER, DI_MIRROR_RENDER,
DI_XRAY_RENDER, DI_XRAY_RENDER,
#ifdef PREY
DI_PORTAL_RENDER, // HUMANHEAD
DI_SKYBOX_RENDER, // HUMANHEAD tmj
#endif
DI_REMOTE_RENDER DI_REMOTE_RENDER
} dynamicidImage_t; } dynamicidImage_t;
@@ -115,6 +119,9 @@ typedef enum {
OP_TYPE_AND, OP_TYPE_AND,
OP_TYPE_OR, OP_TYPE_OR,
OP_TYPE_SOUND OP_TYPE_SOUND
#ifdef PREY
, OP_TYPE_FRAGMENTPROGRAMS // HUMANHEAD CJR: fragment program support toggle
#endif
} expOpType_t; } expOpType_t;
typedef enum { typedef enum {
@@ -188,6 +195,9 @@ typedef enum {
SL_BUMP, SL_BUMP,
SL_DIFFUSE, SL_DIFFUSE,
SL_SPECULAR SL_SPECULAR
#ifdef PREY
, SL_SHADER
#endif
} stageLighting_t; } stageLighting_t;
// cross-blended terrain textures need to modulate the color by // cross-blended terrain textures need to modulate the color by
@@ -199,12 +209,21 @@ typedef enum {
} stageVertexColor_t; } stageVertexColor_t;
static const int MAX_FRAGMENT_IMAGES = 8; static const int MAX_FRAGMENT_IMAGES = 8;
#ifdef PREY
static const int MAX_VERTEX_PARMS = 8;
static const int MAX_FRAGMENT_PARMS = 8;
#else
static const int MAX_VERTEX_PARMS = 4; static const int MAX_VERTEX_PARMS = 4;
#endif
typedef struct { typedef struct {
int vertexProgram; int vertexProgram;
int numVertexParms; int numVertexParms;
int vertexParms[MAX_VERTEX_PARMS][4]; // evaluated register indexes int vertexParms[MAX_VERTEX_PARMS][4]; // evaluated register indexes
#ifdef PREY
int numFragmentParms;
int fragmentParms[MAX_FRAGMENT_PARMS][4]; // evaluated register indexes
#endif
int fragmentProgram; int fragmentProgram;
int numFragmentProgramImages; int numFragmentProgramImages;
@@ -213,6 +232,14 @@ typedef struct {
idMegaTexture* megaTexture; // handles all the binding and parameter setting idMegaTexture* megaTexture; // handles all the binding and parameter setting
} newShaderStage_t; } newShaderStage_t;
#ifdef PREY
// HUMANHEAD bjk: specular exponent/brightness parsed by specularExp.
typedef struct {
float exponent;
float brightness;
} specData_t;
#endif
typedef struct { typedef struct {
int conditionRegister; // if registers[conditionRegister] == 0, skip stage int conditionRegister; // if registers[conditionRegister] == 0, skip stage
stageLighting_t lighting; // determines which passes interact with lights stageLighting_t lighting; // determines which passes interact with lights
@@ -225,8 +252,20 @@ typedef struct {
bool ignoreAlphaTest; // this stage should act as translucent, even bool ignoreAlphaTest; // this stage should act as translucent, even
// if the surface is alpha tested // if the surface is alpha tested
float privatePolygonOffset; // a per-stage polygon offset float privatePolygonOffset; // a per-stage polygon offset
#ifdef PREY
bool isGlow; // HUMANHEAD CJR: Glow overlay
bool isScopeView; // HUMANHEAD CJR: Scope view
bool isShuttleView; // HUMANHEAD pdm: shuttle view
bool isNotScopeView; // HUMANHEAD CJR
bool isSpiritWalk; // HUMANHEAD CJR
bool isNotSpiritWalk; // HUMANHEAD CJR
#endif
newShaderStage_t* newStage; // vertex / fragment program based stage newShaderStage_t* newStage; // vertex / fragment program based stage
#ifdef PREY
specData_t specular; // HUMANHEAD bjk
#endif
} shaderStage_t; } shaderStage_t;
typedef enum { typedef enum {
@@ -268,7 +307,11 @@ const int MAX_SHADER_STAGES = 256;
const int MAX_TEXGEN_REGISTERS = 4; const int MAX_TEXGEN_REGISTERS = 4;
#ifdef PREY
const int MAX_ENTITY_SHADER_PARMS = 13; // HUMANHEAD pdm: increased from 12
#else
const int MAX_ENTITY_SHADER_PARMS = 12; const int MAX_ENTITY_SHADER_PARMS = 12;
#endif
// material flags // material flags
typedef enum { typedef enum {
@@ -675,6 +718,9 @@ private:
void ParseSort(idLexer& src); void ParseSort(idLexer& src);
void ParseBlend(idLexer& src, shaderStage_t* stage); void ParseBlend(idLexer& src, shaderStage_t* stage);
void ParseVertexParm(idLexer& src, newShaderStage_t* newStage); void ParseVertexParm(idLexer& src, newShaderStage_t* newStage);
#ifdef PREY
void ParseFragmentParm(idLexer& src, newShaderStage_t* newStage);
#endif
void ParseFragmentMap(idLexer& src, newShaderStage_t* newStage); void ParseFragmentMap(idLexer& src, newShaderStage_t* newStage);
void ParseStage(idLexer& src, const textureRepeat_t trpDefault = TR_REPEAT); void ParseStage(idLexer& src, const textureRepeat_t trpDefault = TR_REPEAT);
void ParseDeform(idLexer& src); void ParseDeform(idLexer& src);