2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2016-07-02 09:22:04 +00:00
Copyright ( C ) 2014 - 2016 Robert Beckebans
Copyright ( C ) 2014 - 2016 Kot in Action Creative Artel
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# ifndef __MATERIAL_H__
# define __MATERIAL_H__
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Material
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
class idImage ;
class idCinematic ;
class idUserInterface ;
// moved from image.h for default parm
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
TF_LINEAR ,
TF_NEAREST ,
2016-01-09 12:38:49 +00:00
TF_NEAREST_MIPMAP , // RB: no linear interpolation but explicit mip-map levels for hierarchical depth buffer
2012-11-26 18:58:24 +00:00
TF_DEFAULT // use the user-specified r_textureFilter
} textureFilter_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
TR_REPEAT ,
TR_CLAMP ,
TR_CLAMP_TO_ZERO , // guarantee 0,0,0,255 edge for projected textures
TR_CLAMP_TO_ZERO_ALPHA // guarantee 0 alpha edge for projected textures
} textureRepeat_t ;
2012-11-28 15:47:07 +00:00
typedef struct
{
2012-11-26 18:58:24 +00:00
int stayTime ; // msec for no change
int fadeTime ; // msec to fade vertex colors over
float start [ 4 ] ; // vertex color at spawn (possibly out of 0.0 - 1.0 range, will clamp after calc)
float end [ 4 ] ; // vertex color at fade-out (possibly out of 0.0 - 1.0 range, will clamp after calc)
} decalInfo_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
DFRM_NONE ,
DFRM_SPRITE ,
DFRM_TUBE ,
DFRM_FLARE ,
DFRM_EXPAND ,
DFRM_MOVE ,
DFRM_EYEBALL ,
DFRM_PARTICLE ,
DFRM_PARTICLE2 ,
DFRM_TURB
} deform_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
DI_STATIC ,
DI_SCRATCH , // video, screen wipe, etc
DI_CUBE_RENDER ,
DI_MIRROR_RENDER ,
DI_XRAY_RENDER ,
DI_REMOTE_RENDER
} dynamicidImage_t ;
// note: keep opNames[] in sync with changes
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
OP_TYPE_ADD ,
OP_TYPE_SUBTRACT ,
OP_TYPE_MULTIPLY ,
OP_TYPE_DIVIDE ,
OP_TYPE_MOD ,
OP_TYPE_TABLE ,
OP_TYPE_GT ,
OP_TYPE_GE ,
OP_TYPE_LT ,
OP_TYPE_LE ,
OP_TYPE_EQ ,
OP_TYPE_NE ,
OP_TYPE_AND ,
OP_TYPE_OR ,
OP_TYPE_SOUND
} expOpType_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
EXP_REG_TIME ,
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
EXP_REG_PARM0 ,
EXP_REG_PARM1 ,
EXP_REG_PARM2 ,
EXP_REG_PARM3 ,
EXP_REG_PARM4 ,
EXP_REG_PARM5 ,
EXP_REG_PARM6 ,
EXP_REG_PARM7 ,
EXP_REG_PARM8 ,
EXP_REG_PARM9 ,
EXP_REG_PARM10 ,
EXP_REG_PARM11 ,
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
EXP_REG_GLOBAL0 ,
EXP_REG_GLOBAL1 ,
EXP_REG_GLOBAL2 ,
EXP_REG_GLOBAL3 ,
EXP_REG_GLOBAL4 ,
EXP_REG_GLOBAL5 ,
EXP_REG_GLOBAL6 ,
EXP_REG_GLOBAL7 ,
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
EXP_REG_NUM_PREDEFINED
} expRegister_t ;
2012-11-28 15:47:07 +00:00
typedef struct
{
expOpType_t opType ;
2012-11-26 18:58:24 +00:00
int a , b , c ;
} expOp_t ;
2012-11-28 15:47:07 +00:00
typedef struct
{
2012-11-26 18:58:24 +00:00
int registers [ 4 ] ;
} colorStage_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
TG_EXPLICIT ,
TG_DIFFUSE_CUBE ,
TG_REFLECT_CUBE ,
TG_SKYBOX_CUBE ,
TG_WOBBLESKY_CUBE ,
TG_SCREEN , // screen aligned, for mirrorRenders and screen space temporaries
TG_SCREEN2 ,
TG_GLASSWARP
} texgen_t ;
2012-11-28 15:47:07 +00:00
typedef struct
{
idCinematic * cinematic ;
idImage * image ;
2012-11-26 18:58:24 +00:00
texgen_t texgen ;
bool hasMatrix ;
int matrix [ 2 ] [ 3 ] ; // we only allow a subset of the full projection matrix
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// dynamic image variables
dynamicidImage_t dynamic ;
int width , height ;
int dynamicFrameCount ;
} textureStage_t ;
// the order BUMP / DIFFUSE / SPECULAR is necessary for interactions to draw correctly on low end cards
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
SL_AMBIENT , // execute after lighting
SL_BUMP ,
SL_DIFFUSE ,
SL_SPECULAR ,
SL_COVERAGE ,
} stageLighting_t ;
// cross-blended terrain textures need to modulate the color by
// the vertex color to smoothly blend between two textures
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
SVC_IGNORE ,
SVC_MODULATE ,
SVC_INVERSE_MODULATE
} stageVertexColor_t ;
static const int MAX_FRAGMENT_IMAGES = 8 ;
static const int MAX_VERTEX_PARMS = 4 ;
2012-11-28 15:47:07 +00:00
typedef struct
{
2012-11-26 18:58:24 +00:00
int vertexProgram ;
int numVertexParms ;
int vertexParms [ MAX_VERTEX_PARMS ] [ 4 ] ; // evaluated register indexes
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int fragmentProgram ;
int glslProgram ;
int numFragmentProgramImages ;
2012-11-28 15:47:07 +00:00
idImage * fragmentProgramImages [ MAX_FRAGMENT_IMAGES ] ;
2012-11-26 18:58:24 +00:00
} newShaderStage_t ;
2012-11-28 15:47:07 +00:00
typedef struct
{
2012-11-26 18:58:24 +00:00
int conditionRegister ; // if registers[conditionRegister] == 0, skip stage
stageLighting_t lighting ; // determines which passes interact with lights
uint64 drawStateBits ;
colorStage_t color ;
bool hasAlphaTest ;
int alphaTestRegister ;
textureStage_t texture ;
stageVertexColor_t vertexColor ;
bool ignoreAlphaTest ; // this stage should act as translucent, even
2012-11-28 15:47:07 +00:00
// if the surface is alpha tested
2012-11-26 18:58:24 +00:00
float privatePolygonOffset ; // a per-stage polygon offset
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
newShaderStage_t * newStage ; // vertex / fragment program based stage
2012-11-26 18:58:24 +00:00
} shaderStage_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
MC_BAD ,
MC_OPAQUE , // completely fills the triangle, will have black drawn on fillDepthBuffer
MC_PERFORATED , // may have alpha tested holes
MC_TRANSLUCENT // blended with background
} materialCoverage_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
SS_SUBVIEW = - 3 , // mirrors, viewscreens, etc
SS_GUI = - 2 , // guis
SS_BAD = - 1 ,
SS_OPAQUE , // opaque
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
SS_PORTAL_SKY ,
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
SS_DECAL , // scorch marks, etc.
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
SS_FAR ,
SS_MEDIUM , // normal translucent
SS_CLOSE ,
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
SS_ALMOST_NEAREST , // gun smoke puffs
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
SS_NEAREST , // screen blood blobs
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
SS_POST_PROCESS = 100 // after a screen copy to texture
} materialSort_t ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
CT_FRONT_SIDED ,
CT_BACK_SIDED ,
CT_TWO_SIDED
} cullType_t ;
// these don't effect per-material storage, so they can be very large
const int MAX_SHADER_STAGES = 256 ;
const int MAX_TEXGEN_REGISTERS = 4 ;
const int MAX_ENTITY_SHADER_PARMS = 12 ;
const int MAX_GLOBAL_SHADER_PARMS = 12 ; // ? this looks like it should only be 8
// material flags
2012-11-28 15:47:07 +00:00
typedef enum
{
MF_DEFAULTED = BIT ( 0 ) ,
MF_POLYGONOFFSET = BIT ( 1 ) ,
MF_NOSHADOWS = BIT ( 2 ) ,
MF_FORCESHADOWS = BIT ( 3 ) ,
MF_NOSELFSHADOW = BIT ( 4 ) ,
2016-07-02 09:22:04 +00:00
MF_NOPORTALFOG = BIT ( 5 ) , // this fog volume won't ever consider a portal fogged out
MF_EDITOR_VISIBLE = BIT ( 6 ) , // in use (visible) per editor
// motorsep 11-23-2014; material LOD keys that define what LOD iteration the surface falls into
MF_LOD1_SHIFT = 7 ,
MF_LOD1 = BIT ( 7 ) , // motorsep 11-24-2014; material flag for LOD1 iteration
MF_LOD2 = BIT ( 8 ) , // motorsep 11-24-2014; material flag for LOD2 iteration
MF_LOD3 = BIT ( 9 ) , // motorsep 11-24-2014; material flag for LOD3 iteration
MF_LOD4 = BIT ( 10 ) , // motorsep 11-24-2014; material flag for LOD4 iteration
MF_LOD_PERSISTENT = BIT ( 11 ) // motorsep 11-24-2014; material flag for persistent LOD iteration
2012-11-26 18:58:24 +00:00
} materialFlags_t ;
// contents flags, NOTE: make sure to keep the defines in doom_defs.script up to date with these!
2012-11-28 15:47:07 +00:00
typedef enum
{
CONTENTS_SOLID = BIT ( 0 ) , // an eye is never valid in a solid
CONTENTS_OPAQUE = BIT ( 1 ) , // blocks visibility (for ai)
CONTENTS_WATER = BIT ( 2 ) , // used for water
CONTENTS_PLAYERCLIP = BIT ( 3 ) , // solid to players
CONTENTS_MONSTERCLIP = BIT ( 4 ) , // solid to monsters
CONTENTS_MOVEABLECLIP = BIT ( 5 ) , // solid to moveable entities
CONTENTS_IKCLIP = BIT ( 6 ) , // solid to IK
CONTENTS_BLOOD = BIT ( 7 ) , // used to detect blood decals
CONTENTS_BODY = BIT ( 8 ) , // used for actors
CONTENTS_PROJECTILE = BIT ( 9 ) , // used for projectiles
CONTENTS_CORPSE = BIT ( 10 ) , // used for dead bodies
CONTENTS_RENDERMODEL = BIT ( 11 ) , // used for render models for collision detection
CONTENTS_TRIGGER = BIT ( 12 ) , // used for triggers
CONTENTS_AAS_SOLID = BIT ( 13 ) , // solid for AAS
CONTENTS_AAS_OBSTACLE = BIT ( 14 ) , // used to compile an obstacle into AAS that can be enabled/disabled
CONTENTS_FLASHLIGHT_TRIGGER = BIT ( 15 ) , // used for triggers that are activated by the flashlight
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// contents used by utils
2012-11-28 15:47:07 +00:00
CONTENTS_AREAPORTAL = BIT ( 20 ) , // portal separating renderer areas
CONTENTS_NOCSG = BIT ( 21 ) , // don't cut this brush with CSG operations in the editor
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
CONTENTS_REMOVE_UTIL = ~ ( CONTENTS_AREAPORTAL | CONTENTS_NOCSG )
2012-11-26 18:58:24 +00:00
} contentsFlags_t ;
// surface types
const int NUM_SURFACE_BITS = 4 ;
const int MAX_SURFACE_TYPES = 1 < < NUM_SURFACE_BITS ;
2012-11-28 15:47:07 +00:00
typedef enum
{
2012-11-26 18:58:24 +00:00
SURFTYPE_NONE , // default type
2012-11-28 15:47:07 +00:00
SURFTYPE_METAL ,
2012-11-26 18:58:24 +00:00
SURFTYPE_STONE ,
SURFTYPE_FLESH ,
SURFTYPE_WOOD ,
SURFTYPE_CARDBOARD ,
SURFTYPE_LIQUID ,
SURFTYPE_GLASS ,
SURFTYPE_PLASTIC ,
SURFTYPE_RICOCHET ,
SURFTYPE_10 ,
SURFTYPE_11 ,
SURFTYPE_12 ,
SURFTYPE_13 ,
SURFTYPE_14 ,
SURFTYPE_15
} surfTypes_t ;
// surface flags
2012-11-28 15:47:07 +00:00
typedef enum
{
SURF_TYPE_BIT0 = BIT ( 0 ) , // encodes the material type (metal, flesh, concrete, etc.)
SURF_TYPE_BIT1 = BIT ( 1 ) , // "
SURF_TYPE_BIT2 = BIT ( 2 ) , // "
SURF_TYPE_BIT3 = BIT ( 3 ) , // "
2012-11-26 18:58:24 +00:00
SURF_TYPE_MASK = ( 1 < < NUM_SURFACE_BITS ) - 1 ,
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
SURF_NODAMAGE = BIT ( 4 ) , // never give falling damage
SURF_SLICK = BIT ( 5 ) , // effects game physics
SURF_COLLISION = BIT ( 6 ) , // collision surface
SURF_LADDER = BIT ( 7 ) , // player can climb up this surface
SURF_NOIMPACT = BIT ( 8 ) , // don't make missile explosions
SURF_NOSTEPS = BIT ( 9 ) , // no footstep sounds
SURF_DISCRETE = BIT ( 10 ) , // not clipped or merged by utilities
SURF_NOFRAGMENT = BIT ( 11 ) , // dmap won't cut surface at each bsp boundary
SURF_NULLNORMAL = BIT ( 12 ) // renderbump will draw this surface as 0x80 0x80 0x80, which
// won't collect light from any angle
2012-11-26 18:58:24 +00:00
} surfaceFlags_t ;
class idSoundEmitter ;
2012-11-28 15:47:07 +00:00
class idMaterial : public idDecl
{
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
idMaterial ( ) ;
2012-11-26 18:58:24 +00:00
virtual ~ idMaterial ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
virtual size_t Size ( ) const ;
virtual bool SetDefaultText ( ) ;
2012-11-28 15:47:07 +00:00
virtual const char * DefaultDefinition ( ) const ;
virtual bool Parse ( const char * text , const int textLength , bool allowBinaryVersion ) ;
2012-11-26 18:58:24 +00:00
virtual void FreeData ( ) ;
virtual void Print ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//BSM Nerve: Added for material editor
2012-11-28 15:47:07 +00:00
bool Save ( const char * fileName = NULL ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns the internal image name for stage 0, which can be used
// for the renderer CaptureRenderToImage() call
// I'm not really sure why this needs to be virtual...
virtual const char * ImageName ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
void ReloadImages ( bool force ) const ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns number of stages this material contains
const int GetNumStages ( ) const
{
return numStages ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// if the material is simple, all that needs to be known are
// the images for drawing.
// These will either all return valid images, or all return NULL
idImage * GetFastPathBumpImage ( ) const
{
return fastPathBumpImage ;
} ;
idImage * GetFastPathDiffuseImage ( ) const
{
return fastPathDiffuseImage ;
} ;
idImage * GetFastPathSpecularImage ( ) const
{
return fastPathSpecularImage ;
} ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// get a specific stage
const shaderStage_t * GetStage ( const int index ) const
{
assert ( index > = 0 & & index < numStages ) ;
return & stages [ index ] ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// get the first bump map stage, or NULL if not present.
// used for bumpy-specular
const shaderStage_t * GetBumpStage ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if the material will draw anything at all. Triggers, portals,
// etc, will not have anything to draw. A not drawn surface can still castShadow,
// which can be used to make a simplified shadow hull for a complex object set
// as noShadow
bool IsDrawn ( ) const
{
return ( numStages > 0 | | entityGui ! = 0 | | gui ! = NULL ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if the material will draw any non light interaction stages
bool HasAmbient ( ) const
{
return ( numAmbientStages > 0 ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if material has a gui
bool HasGui ( ) const
{
return ( entityGui ! = 0 | | gui ! = NULL ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if the material will generate another view, either as
// a mirror or dynamic rendered image
bool HasSubview ( ) const
{
return hasSubview ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if the material will generate shadows, not making a
// distinction between global and no-self shadows
bool SurfaceCastsShadow ( ) const
{
return TestMaterialFlag ( MF_FORCESHADOWS ) | | ! TestMaterialFlag ( MF_NOSHADOWS ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if the material will generate interactions with fog/blend lights
// All non-translucent surfaces receive fog unless they are explicitly noFog
bool ReceivesFog ( ) const
{
return ( IsDrawn ( ) & & ! noFog & & coverage ! = MC_TRANSLUCENT ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if the material will generate interactions with normal lights
// Many special effect surfaces don't have any bump/diffuse/specular
// stages, and don't interact with lights at all
bool ReceivesLighting ( ) const
{
return numAmbientStages ! = numStages ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if the material should generate interactions on sides facing away
// from light centers, as with noshadow and noselfshadow options
bool ReceivesLightingOnBackSides ( ) const
{
return ( materialFlags & ( MF_NOSELFSHADOW | MF_NOSHADOWS ) ) ! = 0 ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// Standard two-sided triangle rendering won't work with bump map lighting, because
// the normal and tangent vectors won't be correct for the back sides. When two
// sided lighting is desired. typically for alpha tested surfaces, this is
// addressed by having CleanupModelSurfaces() create duplicates of all the triangles
// with apropriate order reversal.
bool ShouldCreateBackSides ( ) const
{
return shouldCreateBackSides ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// characters and models that are created by a complete renderbump can use a faster
// method of tangent and normal vector generation than surfaces which have a flat
// renderbump wrapped over them.
bool UseUnsmoothedTangents ( ) const
{
return unsmoothedTangents ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// by default, monsters can have blood overlays placed on them, but this can
// be overrided on a per-material basis with the "noOverlays" material command.
// This will always return false for translucent surfaces
bool AllowOverlays ( ) const
{
return allowOverlays ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// MC_OPAQUE, MC_PERFORATED, or MC_TRANSLUCENT, for interaction list linking and
// dmap flood filling
// The depth buffer will not be filled for MC_TRANSLUCENT surfaces
// FIXME: what do nodraw surfaces return?
materialCoverage_t Coverage ( ) const
{
return coverage ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns true if this material takes precedence over other in coplanar cases
bool HasHigherDmapPriority ( const idMaterial & other ) const
{
return ( IsDrawn ( ) & & ! other . IsDrawn ( ) ) | |
( Coverage ( ) < other . Coverage ( ) ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns a idUserInterface if it has a global gui, or NULL if no gui
idUserInterface * GlobalGui ( ) const
{
return gui ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// a discrete surface will never be merged with other surfaces by dmap, which is
// necessary to prevent mutliple gui surfaces, mirrors, autosprites, and some other
// special effects from being combined into a single surface
// guis, merging sprites or other effects, mirrors and remote views are always discrete
bool IsDiscrete ( ) const
{
return ( entityGui | | gui | | deform ! = DFRM_NONE | | sort = = SS_SUBVIEW | |
( surfaceFlags & SURF_DISCRETE ) ! = 0 ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// Normally, dmap chops each surface by every BSP boundary, then reoptimizes.
// For gigantic polygons like sky boxes, this can cause a huge number of planar
// triangles that make the optimizer take forever to turn back into a single
// triangle. The "noFragment" option causes dmap to only break the polygons at
// area boundaries, instead of every BSP boundary. This has the negative effect
// of not automatically fixing up interpenetrations, so when this is used, you
// should manually make the edges of your sky box exactly meet, instead of poking
// into each other.
bool NoFragment ( ) const
{
return ( surfaceFlags & SURF_NOFRAGMENT ) ! = 0 ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------------------------------------------
// light shader specific functions, only called for light entities
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// lightshader option to fill with fog from viewer instead of light from center
bool IsFogLight ( ) const
{
return fogLight ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// perform simple blending of the projection, instead of interacting with bumps and textures
bool IsBlendLight ( ) const
{
return blendLight ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// an ambient light has non-directional bump mapping and no specular
bool IsAmbientLight ( ) const
{
return ambientLight ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// implicitly no-shadows lights (ambients, fogs, etc) will never cast shadows
// but individual light entities can also override this value
bool LightCastsShadows ( ) const
{
return TestMaterialFlag ( MF_FORCESHADOWS ) | |
( ! fogLight & & ! ambientLight & & ! blendLight & & ! TestMaterialFlag ( MF_NOSHADOWS ) ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// fog lights, blend lights, ambient lights, etc will all have to have interaction
// triangles generated for sides facing away from the light as well as those
// facing towards the light. It is debatable if noshadow lights should effect back
// sides, making everything "noSelfShadow", but that would make noshadow lights
// potentially slower than normal lights, which detracts from their optimization
// ability, so they currently do not.
bool LightEffectsBackSides ( ) const
{
return fogLight | | ambientLight | | blendLight ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// NULL unless an image is explicitly specified in the shader with "lightFalloffShader <image>"
idImage * LightFalloffImage ( ) const
{
return lightFalloffImage ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------------------------------------------
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns the renderbump command line for this shader, or an empty string if not present
const char * GetRenderBump ( ) const
{
return renderBump ;
} ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// set specific material flag(s)
void SetMaterialFlag ( const int flag ) const
{
materialFlags | = flag ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// clear specific material flag(s)
void ClearMaterialFlag ( const int flag ) const
{
materialFlags & = ~ flag ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// test for existance of specific material flag(s)
bool TestMaterialFlag ( const int flag ) const
{
return ( materialFlags & flag ) ! = 0 ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// get content flags
const int GetContentFlags ( ) const
{
return contentFlags ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// get surface flags
const int GetSurfaceFlags ( ) const
{
return surfaceFlags ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// gets name for surface type (stone, metal, flesh, etc.)
const surfTypes_t GetSurfaceType ( ) const
{
return static_cast < surfTypes_t > ( surfaceFlags & SURF_TYPE_MASK ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// get material description
const char * GetDescription ( ) const
{
return desc ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// get sort order
const float GetSort ( ) const
{
return sort ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
const int GetStereoEye ( ) const
{
return stereoEye ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// this is only used by the gui system to force sorting order
// on images referenced from tga's instead of materials.
// this is done this way as there are 2000 tgas the guis use
void SetSort ( float s ) const
{
sort = s ;
} ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// DFRM_NONE, DFRM_SPRITE, etc
deform_t Deform ( ) const
{
return deform ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// flare size, expansion size, etc
const int GetDeformRegister ( int index ) const
{
return deformRegisters [ index ] ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// particle system to emit from surface and table for turbulent
const idDecl * GetDeformDecl ( ) const
{
return deformDecl ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// currently a surface can only have one unique texgen for all the stages
2012-11-26 18:58:24 +00:00
texgen_t Texgen ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// wobble sky parms
const int * GetTexGenRegisters ( ) const
{
return texGenRegisters ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// get cull type
const cullType_t GetCullType ( ) const
{
return cullType ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
float GetEditorAlpha ( ) const
{
return editorAlpha ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
int GetEntityGui ( ) const
{
return entityGui ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
decalInfo_t GetDecalInfo ( ) const
{
return decalInfo ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// spectrums are used for "invisible writing" that can only be
// illuminated by a light of matching spectrum
int Spectrum ( ) const
{
return spectrum ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
float GetPolygonOffset ( ) const
{
return polygonOffset ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
float GetSurfaceArea ( ) const
{
return surfaceArea ;
}
void AddToSurfaceArea ( float area )
{
surfaceArea + = area ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------------------------------------------
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns the length, in milliseconds, of the videoMap on this material,
// or zero if it doesn't have one
2012-11-26 18:58:24 +00:00
int CinematicLength ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
void CloseCinematic ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
void ResetCinematicTime ( int time ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int GetCinematicStartTime ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
void UpdateCinematic ( int time ) const ;
2019-11-11 19:27:44 +00:00
2014-04-21 21:56:46 +00:00
// RB: added because we can't rely on the FFmpeg feedback how long a video really is
bool CinematicIsPlaying ( ) const ;
// RB end
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------------------------------------------
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// gets an image for the editor to use
idImage * GetEditorImage ( ) const ;
2012-11-26 18:58:24 +00:00
int GetImageWidth ( ) const ;
int GetImageHeight ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
void SetGui ( const char * _gui ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------------------------------------------
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// returns number of registers this material contains
const int GetNumRegisters ( ) const
{
return numRegisters ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// Regs should point to a float array large enough to hold GetNumRegisters() floats.
// FloatTime is passed in because different entities, which may be running in parallel,
// can be in different time groups.
void EvaluateRegisters (
float * registers ,
const float localShaderParms [ MAX_ENTITY_SHADER_PARMS ] ,
const float globalShaderParms [ MAX_GLOBAL_SHADER_PARMS ] ,
const float floatTime ,
idSoundEmitter * soundEmitter ) const ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// if a material only uses constants (no entityParm or globalparm references), this
// will return a pointer to an internal table, and EvaluateRegisters will not need
// to be called. If NULL is returned, EvaluateRegisters must be used.
const float * ConstantRegisters ( ) const
{
return constantRegisters ;
} ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
bool SuppressInSubview ( ) const
{
return suppressInSubview ;
} ;
bool IsPortalSky ( ) const
{
return portalSky ;
} ;
2012-11-26 18:58:24 +00:00
void AddReference ( ) ;
2019-11-11 19:27:44 +00:00
2016-07-02 09:22:04 +00:00
// motorsep 11-23-2014; material LOD keys that define what LOD iteration the surface falls into
// lod1 - lod4 defines several levels of LOD
// persistentLOD specifies the LOD iteration that still being rendered, even after the camera is beyond the distance at which LOD iteration should not be rendered
2019-11-11 19:27:44 +00:00
2016-07-02 09:22:04 +00:00
bool IsLOD ( ) const
{
return ( materialFlags & ( MF_LOD1 | MF_LOD2 | MF_LOD3 | MF_LOD4 ) ) ! = 0 ;
}
// foresthale 2014-11-24: added IsLODVisibleForDistance method
bool IsLODVisibleForDistance ( float distance , float lodBase ) const
{
int bit = ( materialFlags & ( MF_LOD1 | MF_LOD2 | MF_LOD3 | MF_LOD4 ) ) > > MF_LOD1_SHIFT ;
float m1 = lodBase * ( bit > > 1 ) ;
float m2 = lodBase * bit ;
return distance > = m1 & & ( distance < m2 | | ( materialFlags & ( MF_LOD_PERSISTENT ) ) ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
private :
// parse the entire material
void CommonInit ( ) ;
2012-11-28 15:47:07 +00:00
void ParseMaterial ( idLexer & src ) ;
bool MatchToken ( idLexer & src , const char * match ) ;
void ParseSort ( idLexer & src ) ;
void ParseStereoEye ( idLexer & src ) ;
void ParseBlend ( idLexer & src , shaderStage_t * stage ) ;
void ParseVertexParm ( idLexer & src , newShaderStage_t * newStage ) ;
void ParseVertexParm2 ( idLexer & src , newShaderStage_t * newStage ) ;
void ParseFragmentMap ( idLexer & src , newShaderStage_t * newStage ) ;
void ParseStage ( idLexer & src , const textureRepeat_t trpDefault = TR_REPEAT ) ;
void ParseDeform ( idLexer & src ) ;
void ParseDecalInfo ( idLexer & src ) ;
bool CheckSurfaceParm ( idToken * token ) ;
2012-11-26 18:58:24 +00:00
int GetExpressionConstant ( float f ) ;
int GetExpressionTemporary ( ) ;
2012-11-28 15:47:07 +00:00
expOp_t * GetExpressionOp ( ) ;
2012-11-26 18:58:24 +00:00
int EmitOp ( int a , int b , expOpType_t opType ) ;
2012-11-28 15:47:07 +00:00
int ParseEmitOp ( idLexer & src , int a , expOpType_t opType , int priority ) ;
int ParseTerm ( idLexer & src ) ;
int ParseExpressionPriority ( idLexer & src , int priority ) ;
int ParseExpression ( idLexer & src ) ;
void ClearStage ( shaderStage_t * ss ) ;
int NameToSrcBlendMode ( const idStr & name ) ;
int NameToDstBlendMode ( const idStr & name ) ;
void MultiplyTextureMatrix ( textureStage_t * ts , int registers [ 2 ] [ 3 ] ) ; // FIXME: for some reason the const is bad for gcc and Mac
2012-11-26 18:58:24 +00:00
void SortInteractionStages ( ) ;
void AddImplicitStages ( const textureRepeat_t trpDefault = TR_REPEAT ) ;
void CheckForConstantRegisters ( ) ;
void SetFastPathImages ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
private :
idStr desc ; // description
idStr renderBump ; // renderbump command options, without the "renderbump" at the start
2019-11-11 19:27:44 +00:00
2016-07-02 09:22:04 +00:00
idImage * lightFalloffImage ; // only for light shaders
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idImage * fastPathBumpImage ; // if any of these are set, they all will be
idImage * fastPathDiffuseImage ;
idImage * fastPathSpecularImage ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int entityGui ; // draw a gui with the idUserInterface from the renderEntity_t
2012-11-28 15:47:07 +00:00
// non zero will draw gui, gui2, or gui3 from renderEnitty_t
mutable idUserInterface * gui ; // non-custom guis are shared by all users of a material
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
bool noFog ; // surface does not create fog interactions
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int spectrum ; // for invisible writing, used for both lights and surfaces
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
float polygonOffset ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int contentFlags ; // content flags
2012-11-28 15:47:07 +00:00
int surfaceFlags ; // surface flags
2012-11-26 18:58:24 +00:00
mutable int materialFlags ; // material flags
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
decalInfo_t decalInfo ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
mutable float sort ; // lower numbered shaders draw before higher numbered
int stereoEye ;
deform_t deform ;
int deformRegisters [ 4 ] ; // numeric parameter for deforms
2012-11-28 15:47:07 +00:00
const idDecl * deformDecl ; // for surface emitted particle deforms and tables
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int texGenRegisters [ MAX_TEXGEN_REGISTERS ] ; // for wobbleSky
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
materialCoverage_t coverage ;
cullType_t cullType ; // CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED
bool shouldCreateBackSides ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
bool fogLight ;
bool blendLight ;
bool ambientLight ;
bool unsmoothedTangents ;
bool hasSubview ; // mirror, remote render, etc
bool allowOverlays ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int numOps ;
2012-11-28 15:47:07 +00:00
expOp_t * ops ; // evaluate to make expressionRegisters
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int numRegisters ; //
2012-11-28 15:47:07 +00:00
float * expressionRegisters ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
float * constantRegisters ; // NULL if ops ever reference globalParms or entityParms
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int numStages ;
int numAmbientStages ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
shaderStage_t * stages ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
struct mtrParsingData_s * pd ; // only used during parsing
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
float surfaceArea ; // only for listSurfaceAreas
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// we defer loading of the editor image until it is asked for, so the game doesn't load up
// all the invisible and uncompressed images.
// If editorImage is NULL, it will atempt to load editorImageName, and set editorImage to that or defaultImage
idStr editorImageName ;
2012-11-28 15:47:07 +00:00
mutable idImage * editorImage ; // image used for non-shaded preview
2012-11-26 18:58:24 +00:00
float editorAlpha ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
bool suppressInSubview ;
bool portalSky ;
int refCount ;
} ;
2012-11-28 15:47:07 +00:00
typedef idList < const idMaterial * , TAG_MATERIAL > idMatList ;
2012-11-26 18:58:24 +00:00
# endif /* !__MATERIAL_H__ */