664 lines
28 KiB
C++
664 lines
28 KiB
C++
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||
//
|
||
// Purpose:
|
||
//
|
||
// $NoKeywords: $
|
||
//
|
||
//===========================================================================//
|
||
|
||
#ifndef IMATERIAL_H
|
||
#define IMATERIAL_H
|
||
|
||
#ifdef _WIN32
|
||
#pragma once
|
||
#endif
|
||
|
||
#include "bitmap/imageformat.h"
|
||
#include "materialsystem/imaterialsystem.h"
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Forward declarations
|
||
//-----------------------------------------------------------------------------
|
||
|
||
class IMaterialVar;
|
||
class ITexture;
|
||
class IMaterialProxy;
|
||
class Vector;
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Flags for GetVertexFormat
|
||
//-----------------------------------------------------------------------------
|
||
enum VertexFormatFlags_t
|
||
{
|
||
// Indicates an uninitialized VertexFormat_t value
|
||
VERTEX_FORMAT_INVALID = 0xFFFFFFFFFFFFFFFFull,
|
||
|
||
VERTEX_POSITION = 0x0001,
|
||
VERTEX_NORMAL = 0x0002,
|
||
VERTEX_COLOR = 0x0004,
|
||
VERTEX_SPECULAR = 0x0008,
|
||
|
||
VERTEX_TANGENT_S = 0x0010,
|
||
VERTEX_TANGENT_T = 0x0020,
|
||
VERTEX_TANGENT_SPACE= VERTEX_TANGENT_S | VERTEX_TANGENT_T,
|
||
|
||
// Indicates we're using wrinkle
|
||
VERTEX_WRINKLE = 0x0040,
|
||
|
||
// Indicates we're using bone indices
|
||
VERTEX_BONE_INDEX = 0x0080,
|
||
|
||
// Indicates this expects a color stream on stream 1
|
||
VERTEX_COLOR_STREAM_1 = 0x0100,
|
||
|
||
// Indicates this format shouldn't be bloated to cache align it
|
||
// (only used for VertexUsage)
|
||
VERTEX_FORMAT_USE_EXACT_FORMAT = 0x0200,
|
||
|
||
// Indicates that compressed vertex elements are to be used (see also VertexCompressionType_t)
|
||
VERTEX_FORMAT_COMPRESSED = 0x400,
|
||
|
||
// Position or normal (if present) should be 4D not 3D
|
||
VERTEX_FORMAT_PAD_POS_NORM = 0x800,
|
||
|
||
// Update this if you add or remove bits...
|
||
VERTEX_LAST_BIT = 11,
|
||
|
||
VERTEX_BONE_WEIGHT_BIT = VERTEX_LAST_BIT + 1,
|
||
USER_DATA_SIZE_BIT = VERTEX_LAST_BIT + 4,
|
||
TEX_COORD_SIZE_BIT = VERTEX_LAST_BIT + 7,
|
||
|
||
VERTEX_BONE_WEIGHT_MASK = ( 0x7 << VERTEX_BONE_WEIGHT_BIT ),
|
||
USER_DATA_SIZE_MASK = ( 0x7 << USER_DATA_SIZE_BIT ),
|
||
|
||
VERTEX_FORMAT_FIELD_MASK = 0x0FF,
|
||
|
||
// If everything is off, it's an unknown vertex format
|
||
VERTEX_FORMAT_UNKNOWN = 0,
|
||
};
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Macros for construction..
|
||
//-----------------------------------------------------------------------------
|
||
#define VERTEX_BONEWEIGHT( _n ) ((_n) << VERTEX_BONE_WEIGHT_BIT)
|
||
#define VERTEX_USERDATA_SIZE( _n ) ((_n) << USER_DATA_SIZE_BIT)
|
||
#define VERTEX_TEXCOORD_MASK( _coord ) (( 0x7ULL ) << ( TEX_COORD_SIZE_BIT + 3 * (_coord) ))
|
||
|
||
inline VertexFormat_t VERTEX_TEXCOORD_SIZE( int nIndex, int nNumCoords )
|
||
{
|
||
uint64 n64=nNumCoords;
|
||
uint64 nShift=TEX_COORD_SIZE_BIT + (3*nIndex);
|
||
return n64 << nShift;
|
||
}
|
||
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Gets at various vertex format info...
|
||
//-----------------------------------------------------------------------------
|
||
inline int VertexFlags( VertexFormat_t vertexFormat )
|
||
{
|
||
return static_cast<int> ( vertexFormat & ( (1 << (VERTEX_LAST_BIT+1)) - 1 ) );
|
||
}
|
||
|
||
inline int NumBoneWeights( VertexFormat_t vertexFormat )
|
||
{
|
||
return static_cast<int> ( (vertexFormat >> VERTEX_BONE_WEIGHT_BIT) & 0x7 );
|
||
}
|
||
|
||
inline int UserDataSize( VertexFormat_t vertexFormat )
|
||
{
|
||
return static_cast<int> ( (vertexFormat >> USER_DATA_SIZE_BIT) & 0x7 );
|
||
}
|
||
|
||
inline int TexCoordSize( int nTexCoordIndex, VertexFormat_t vertexFormat )
|
||
{
|
||
return static_cast<int> ( (vertexFormat >> (TEX_COORD_SIZE_BIT + 3*nTexCoordIndex) ) & 0x7 );
|
||
}
|
||
|
||
inline VertexCompressionType_t CompressionType( VertexFormat_t vertexFormat )
|
||
{
|
||
// This is trivial now, but we may add multiple flavors of compressed vertex later on
|
||
if ( vertexFormat & VERTEX_FORMAT_COMPRESSED )
|
||
return VERTEX_COMPRESSION_ON;
|
||
else
|
||
return VERTEX_COMPRESSION_NONE;
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// VertexElement_t (enumerates all usable vertex elements)
|
||
//-----------------------------------------------------------------------------
|
||
// FIXME: unify this with VertexFormat_t (i.e. construct the lower bits of VertexFormat_t with "1 << (VertexElement_t)element")
|
||
enum VertexElement_t
|
||
{
|
||
VERTEX_ELEMENT_NONE = -1,
|
||
|
||
// Deliberately explicitly numbered so it's a pain in the ass to change, so you read this:
|
||
// #!#!#NOTE#!#!# update GetVertexElementSize, VertexElementToDeclType and
|
||
// CVBAllocTracker (elementTable) when you update this!
|
||
VERTEX_ELEMENT_POSITION = 0,
|
||
VERTEX_ELEMENT_POSITION4D = 1,
|
||
VERTEX_ELEMENT_NORMAL = 2,
|
||
VERTEX_ELEMENT_NORMAL4D = 3,
|
||
VERTEX_ELEMENT_COLOR = 4,
|
||
VERTEX_ELEMENT_SPECULAR = 5,
|
||
VERTEX_ELEMENT_TANGENT_S = 6,
|
||
VERTEX_ELEMENT_TANGENT_T = 7,
|
||
VERTEX_ELEMENT_WRINKLE = 8,
|
||
VERTEX_ELEMENT_BONEINDEX = 9,
|
||
VERTEX_ELEMENT_BONEWEIGHTS1 = 10,
|
||
VERTEX_ELEMENT_BONEWEIGHTS2 = 11,
|
||
VERTEX_ELEMENT_BONEWEIGHTS3 = 12,
|
||
VERTEX_ELEMENT_BONEWEIGHTS4 = 13,
|
||
VERTEX_ELEMENT_USERDATA1 = 14,
|
||
VERTEX_ELEMENT_USERDATA2 = 15,
|
||
VERTEX_ELEMENT_USERDATA3 = 16,
|
||
VERTEX_ELEMENT_USERDATA4 = 17,
|
||
VERTEX_ELEMENT_TEXCOORD1D_0 = 18,
|
||
VERTEX_ELEMENT_TEXCOORD1D_1 = 19,
|
||
VERTEX_ELEMENT_TEXCOORD1D_2 = 20,
|
||
VERTEX_ELEMENT_TEXCOORD1D_3 = 21,
|
||
VERTEX_ELEMENT_TEXCOORD1D_4 = 22,
|
||
VERTEX_ELEMENT_TEXCOORD1D_5 = 23,
|
||
VERTEX_ELEMENT_TEXCOORD1D_6 = 24,
|
||
VERTEX_ELEMENT_TEXCOORD1D_7 = 25,
|
||
VERTEX_ELEMENT_TEXCOORD2D_0 = 26,
|
||
VERTEX_ELEMENT_TEXCOORD2D_1 = 27,
|
||
VERTEX_ELEMENT_TEXCOORD2D_2 = 28,
|
||
VERTEX_ELEMENT_TEXCOORD2D_3 = 29,
|
||
VERTEX_ELEMENT_TEXCOORD2D_4 = 30,
|
||
VERTEX_ELEMENT_TEXCOORD2D_5 = 31,
|
||
VERTEX_ELEMENT_TEXCOORD2D_6 = 32,
|
||
VERTEX_ELEMENT_TEXCOORD2D_7 = 33,
|
||
VERTEX_ELEMENT_TEXCOORD3D_0 = 34,
|
||
VERTEX_ELEMENT_TEXCOORD3D_1 = 35,
|
||
VERTEX_ELEMENT_TEXCOORD3D_2 = 36,
|
||
VERTEX_ELEMENT_TEXCOORD3D_3 = 37,
|
||
VERTEX_ELEMENT_TEXCOORD3D_4 = 38,
|
||
VERTEX_ELEMENT_TEXCOORD3D_5 = 39,
|
||
VERTEX_ELEMENT_TEXCOORD3D_6 = 40,
|
||
VERTEX_ELEMENT_TEXCOORD3D_7 = 41,
|
||
VERTEX_ELEMENT_TEXCOORD4D_0 = 42,
|
||
VERTEX_ELEMENT_TEXCOORD4D_1 = 43,
|
||
VERTEX_ELEMENT_TEXCOORD4D_2 = 44,
|
||
VERTEX_ELEMENT_TEXCOORD4D_3 = 45,
|
||
VERTEX_ELEMENT_TEXCOORD4D_4 = 46,
|
||
VERTEX_ELEMENT_TEXCOORD4D_5 = 47,
|
||
VERTEX_ELEMENT_TEXCOORD4D_6 = 48,
|
||
VERTEX_ELEMENT_TEXCOORD4D_7 = 49,
|
||
|
||
VERTEX_ELEMENT_NUMELEMENTS = 50
|
||
};
|
||
|
||
inline void Detect_VertexElement_t_Changes( VertexElement_t element ) // GREPs for VertexElement_t will hit this
|
||
{
|
||
// Make it harder for someone to change VertexElement_t without noticing that dependent code
|
||
// (GetVertexElementSize, VertexElementToDeclType, CVBAllocTracker) needs updating
|
||
Assert( VERTEX_ELEMENT_NUMELEMENTS == 50 );
|
||
switch ( element )
|
||
{
|
||
case VERTEX_ELEMENT_POSITION: Assert( VERTEX_ELEMENT_POSITION == 0 ); break;
|
||
case VERTEX_ELEMENT_POSITION4D: Assert( VERTEX_ELEMENT_POSITION4D == 1 ); break;
|
||
case VERTEX_ELEMENT_NORMAL: Assert( VERTEX_ELEMENT_NORMAL == 2 ); break;
|
||
case VERTEX_ELEMENT_NORMAL4D: Assert( VERTEX_ELEMENT_NORMAL4D == 3 ); break;
|
||
case VERTEX_ELEMENT_COLOR: Assert( VERTEX_ELEMENT_COLOR == 4 ); break;
|
||
case VERTEX_ELEMENT_SPECULAR: Assert( VERTEX_ELEMENT_SPECULAR == 5 ); break;
|
||
case VERTEX_ELEMENT_TANGENT_S: Assert( VERTEX_ELEMENT_TANGENT_S == 6 ); break;
|
||
case VERTEX_ELEMENT_TANGENT_T: Assert( VERTEX_ELEMENT_TANGENT_T == 7 ); break;
|
||
case VERTEX_ELEMENT_WRINKLE: Assert( VERTEX_ELEMENT_WRINKLE == 8 ); break;
|
||
case VERTEX_ELEMENT_BONEINDEX: Assert( VERTEX_ELEMENT_BONEINDEX == 9 ); break;
|
||
case VERTEX_ELEMENT_BONEWEIGHTS1: Assert( VERTEX_ELEMENT_BONEWEIGHTS1 == 10 ); break;
|
||
case VERTEX_ELEMENT_BONEWEIGHTS2: Assert( VERTEX_ELEMENT_BONEWEIGHTS2 == 11 ); break;
|
||
case VERTEX_ELEMENT_BONEWEIGHTS3: Assert( VERTEX_ELEMENT_BONEWEIGHTS3 == 12 ); break;
|
||
case VERTEX_ELEMENT_BONEWEIGHTS4: Assert( VERTEX_ELEMENT_BONEWEIGHTS4 == 13 ); break;
|
||
case VERTEX_ELEMENT_USERDATA1: Assert( VERTEX_ELEMENT_USERDATA1 == 14 ); break;
|
||
case VERTEX_ELEMENT_USERDATA2: Assert( VERTEX_ELEMENT_USERDATA2 == 15 ); break;
|
||
case VERTEX_ELEMENT_USERDATA3: Assert( VERTEX_ELEMENT_USERDATA3 == 16 ); break;
|
||
case VERTEX_ELEMENT_USERDATA4: Assert( VERTEX_ELEMENT_USERDATA4 == 17 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_0: Assert( VERTEX_ELEMENT_TEXCOORD1D_0 == 18 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_1: Assert( VERTEX_ELEMENT_TEXCOORD1D_1 == 19 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_2: Assert( VERTEX_ELEMENT_TEXCOORD1D_2 == 20 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_3: Assert( VERTEX_ELEMENT_TEXCOORD1D_3 == 21 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_4: Assert( VERTEX_ELEMENT_TEXCOORD1D_4 == 22 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_5: Assert( VERTEX_ELEMENT_TEXCOORD1D_5 == 23 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_6: Assert( VERTEX_ELEMENT_TEXCOORD1D_6 == 24 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD1D_7: Assert( VERTEX_ELEMENT_TEXCOORD1D_7 == 25 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_0: Assert( VERTEX_ELEMENT_TEXCOORD2D_0 == 26 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_1: Assert( VERTEX_ELEMENT_TEXCOORD2D_1 == 27 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_2: Assert( VERTEX_ELEMENT_TEXCOORD2D_2 == 28 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_3: Assert( VERTEX_ELEMENT_TEXCOORD2D_3 == 29 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_4: Assert( VERTEX_ELEMENT_TEXCOORD2D_4 == 30 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_5: Assert( VERTEX_ELEMENT_TEXCOORD2D_5 == 31 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_6: Assert( VERTEX_ELEMENT_TEXCOORD2D_6 == 32 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD2D_7: Assert( VERTEX_ELEMENT_TEXCOORD2D_7 == 33 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_0: Assert( VERTEX_ELEMENT_TEXCOORD3D_0 == 34 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_1: Assert( VERTEX_ELEMENT_TEXCOORD3D_1 == 35 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_2: Assert( VERTEX_ELEMENT_TEXCOORD3D_2 == 36 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_3: Assert( VERTEX_ELEMENT_TEXCOORD3D_3 == 37 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_4: Assert( VERTEX_ELEMENT_TEXCOORD3D_4 == 38 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_5: Assert( VERTEX_ELEMENT_TEXCOORD3D_5 == 39 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_6: Assert( VERTEX_ELEMENT_TEXCOORD3D_6 == 40 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD3D_7: Assert( VERTEX_ELEMENT_TEXCOORD3D_7 == 41 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_0: Assert( VERTEX_ELEMENT_TEXCOORD4D_0 == 42 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_1: Assert( VERTEX_ELEMENT_TEXCOORD4D_1 == 43 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_2: Assert( VERTEX_ELEMENT_TEXCOORD4D_2 == 44 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_3: Assert( VERTEX_ELEMENT_TEXCOORD4D_3 == 45 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_4: Assert( VERTEX_ELEMENT_TEXCOORD4D_4 == 46 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_5: Assert( VERTEX_ELEMENT_TEXCOORD4D_5 == 47 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_6: Assert( VERTEX_ELEMENT_TEXCOORD4D_6 == 48 ); break;
|
||
case VERTEX_ELEMENT_TEXCOORD4D_7: Assert( VERTEX_ELEMENT_TEXCOORD4D_7 == 49 ); break;
|
||
default:
|
||
Assert( 0 ); // Invalid input or VertexElement_t has definitely changed
|
||
break;
|
||
}
|
||
}
|
||
|
||
// We're testing 2 normal compression methods
|
||
// One compressed normals+tangents into a SHORT2 each (8 bytes total)
|
||
// The other compresses them together, into a single UBYTE4 (4 bytes total)
|
||
// FIXME: pick one or the other, compare lighting quality in important cases
|
||
#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0
|
||
#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1
|
||
//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2
|
||
#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4
|
||
|
||
inline int GetVertexElementSize( VertexElement_t element, VertexCompressionType_t compressionType )
|
||
{
|
||
Detect_VertexElement_t_Changes( element );
|
||
|
||
if ( compressionType == VERTEX_COMPRESSION_ON )
|
||
{
|
||
// Compressed-vertex element sizes
|
||
switch ( element )
|
||
{
|
||
#if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )
|
||
case VERTEX_ELEMENT_NORMAL:
|
||
return ( 2 * sizeof( short ) );
|
||
case VERTEX_ELEMENT_USERDATA4:
|
||
return ( 2 * sizeof( short ) );
|
||
#else //( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )
|
||
// Normals and tangents (userdata4) are combined into a single UBYTE4 vertex element
|
||
case VERTEX_ELEMENT_NORMAL:
|
||
return ( 4 * sizeof( unsigned char ) );
|
||
case VERTEX_ELEMENT_USERDATA4:
|
||
return ( 0 );
|
||
#endif
|
||
// Compressed bone weights use a SHORT2 vertex element:
|
||
case VERTEX_ELEMENT_BONEWEIGHTS1:
|
||
case VERTEX_ELEMENT_BONEWEIGHTS2:
|
||
return ( 2 * sizeof( short ) );
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Uncompressed-vertex element sizes
|
||
switch ( element )
|
||
{
|
||
case VERTEX_ELEMENT_POSITION: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_POSITION4D: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_NORMAL: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_NORMAL4D: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_COLOR: return ( 4 * sizeof( unsigned char ) );
|
||
case VERTEX_ELEMENT_SPECULAR: return ( 4 * sizeof( unsigned char ) );
|
||
case VERTEX_ELEMENT_TANGENT_S: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TANGENT_T: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_WRINKLE: return ( 1 * sizeof( float ) ); // Packed into Position.W
|
||
case VERTEX_ELEMENT_BONEINDEX: return ( 4 * sizeof( unsigned char ) );
|
||
case VERTEX_ELEMENT_BONEWEIGHTS1: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_BONEWEIGHTS2: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_BONEWEIGHTS3: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_BONEWEIGHTS4: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_USERDATA1: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_USERDATA2: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_USERDATA3: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_USERDATA4: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_0: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_1: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_2: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_3: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_4: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_5: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_6: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD1D_7: return ( 1 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_0: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_1: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_2: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_3: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_4: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_5: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_6: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD2D_7: return ( 2 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_0: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_1: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_2: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_3: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_4: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_5: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_6: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD3D_7: return ( 3 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_0: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_1: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_2: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_3: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_4: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_5: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_6: return ( 4 * sizeof( float ) );
|
||
case VERTEX_ELEMENT_TEXCOORD4D_7: return ( 4 * sizeof( float ) );
|
||
default:
|
||
Assert(0);
|
||
return 0;
|
||
};
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Shader state flags can be read from the FLAGS materialvar
|
||
// Also can be read or written to with the Set/GetMaterialVarFlags() call
|
||
// Also make sure you add/remove a string associated with each flag below to CShaderSystem::ShaderStateString in ShaderSystem.cpp
|
||
//-----------------------------------------------------------------------------
|
||
enum MaterialVarFlags_t
|
||
{
|
||
MATERIAL_VAR_DEBUG = (1 << 0),
|
||
MATERIAL_VAR_NO_DEBUG_OVERRIDE = (1 << 1),
|
||
MATERIAL_VAR_NO_DRAW = (1 << 2),
|
||
MATERIAL_VAR_USE_IN_FILLRATE_MODE = (1 << 3),
|
||
|
||
MATERIAL_VAR_VERTEXCOLOR = (1 << 4),
|
||
MATERIAL_VAR_VERTEXALPHA = (1 << 5),
|
||
MATERIAL_VAR_SELFILLUM = (1 << 6),
|
||
MATERIAL_VAR_ADDITIVE = (1 << 7),
|
||
MATERIAL_VAR_ALPHATEST = (1 << 8),
|
||
// MATERIAL_VAR_UNUSED = (1 << 9),
|
||
MATERIAL_VAR_ZNEARER = (1 << 10),
|
||
MATERIAL_VAR_MODEL = (1 << 11),
|
||
MATERIAL_VAR_FLAT = (1 << 12),
|
||
MATERIAL_VAR_NOCULL = (1 << 13),
|
||
MATERIAL_VAR_NOFOG = (1 << 14),
|
||
MATERIAL_VAR_IGNOREZ = (1 << 15),
|
||
MATERIAL_VAR_DECAL = (1 << 16),
|
||
MATERIAL_VAR_ENVMAPSPHERE = (1 << 17), // OBSOLETE
|
||
// MATERIAL_VAR_UNUSED = (1 << 18),
|
||
MATERIAL_VAR_ENVMAPCAMERASPACE = (1 << 19), // OBSOLETE
|
||
MATERIAL_VAR_BASEALPHAENVMAPMASK = (1 << 20),
|
||
MATERIAL_VAR_TRANSLUCENT = (1 << 21),
|
||
MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK = (1 << 22),
|
||
MATERIAL_VAR_NEEDS_SOFTWARE_SKINNING = (1 << 23), // OBSOLETE
|
||
MATERIAL_VAR_OPAQUETEXTURE = (1 << 24),
|
||
MATERIAL_VAR_ENVMAPMODE = (1 << 25), // OBSOLETE
|
||
MATERIAL_VAR_SUPPRESS_DECALS = (1 << 26),
|
||
MATERIAL_VAR_HALFLAMBERT = (1 << 27),
|
||
MATERIAL_VAR_WIREFRAME = (1 << 28),
|
||
MATERIAL_VAR_ALLOWALPHATOCOVERAGE = (1 << 29),
|
||
MATERIAL_VAR_ALPHA_MODIFIED_BY_PROXY = (1 << 30),
|
||
MATERIAL_VAR_VERTEXFOG = (1 << 31),
|
||
|
||
// NOTE: Only add flags here that either should be read from
|
||
// .vmts or can be set directly from client code. Other, internal
|
||
// flags should to into the flag enum in IMaterialInternal.h
|
||
};
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Internal flags not accessible from outside the material system. Stored in Flags2
|
||
//-----------------------------------------------------------------------------
|
||
enum MaterialVarFlags2_t
|
||
{
|
||
// NOTE: These are for $flags2!!!!!
|
||
// UNUSED = (1 << 0),
|
||
|
||
MATERIAL_VAR2_LIGHTING_UNLIT = 0,
|
||
MATERIAL_VAR2_LIGHTING_VERTEX_LIT = (1 << 1),
|
||
MATERIAL_VAR2_LIGHTING_LIGHTMAP = (1 << 2),
|
||
MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP = (1 << 3),
|
||
MATERIAL_VAR2_LIGHTING_MASK =
|
||
( MATERIAL_VAR2_LIGHTING_VERTEX_LIT |
|
||
MATERIAL_VAR2_LIGHTING_LIGHTMAP |
|
||
MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ),
|
||
|
||
// FIXME: Should this be a part of the above lighting enums?
|
||
MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL = (1 << 4),
|
||
MATERIAL_VAR2_USES_ENV_CUBEMAP = (1 << 5),
|
||
MATERIAL_VAR2_NEEDS_TANGENT_SPACES = (1 << 6),
|
||
MATERIAL_VAR2_NEEDS_SOFTWARE_LIGHTING = (1 << 7),
|
||
// GR - HDR path puts lightmap alpha in separate texture...
|
||
MATERIAL_VAR2_BLEND_WITH_LIGHTMAP_ALPHA = (1 << 8),
|
||
MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS = (1 << 9),
|
||
MATERIAL_VAR2_USE_FLASHLIGHT = (1 << 10),
|
||
MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING = (1 << 11),
|
||
MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT = (1 << 12),
|
||
MATERIAL_VAR2_USE_EDITOR = (1 << 13),
|
||
MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE = (1 << 14),
|
||
MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE = (1 << 15),
|
||
MATERIAL_VAR2_IS_SPRITECARD = (1 << 16),
|
||
MATERIAL_VAR2_USES_VERTEXID = (1 << 17),
|
||
MATERIAL_VAR2_SUPPORTS_HW_SKINNING = (1 << 18),
|
||
MATERIAL_VAR2_SUPPORTS_FLASHLIGHT = (1 << 19),
|
||
MATERIAL_VAR2_USE_GBUFFER0 = (1 << 20),
|
||
MATERIAL_VAR2_USE_GBUFFER1 = (1 << 21),
|
||
MATERIAL_VAR2_SELFILLUMMASK = (1 << 22),
|
||
MATERIAL_VAR2_SUPPORTS_TESSELLATION = (1 << 23)
|
||
};
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Preview image return values
|
||
//-----------------------------------------------------------------------------
|
||
enum PreviewImageRetVal_t
|
||
{
|
||
MATERIAL_PREVIEW_IMAGE_BAD = 0,
|
||
MATERIAL_PREVIEW_IMAGE_OK,
|
||
MATERIAL_NO_PREVIEW_IMAGE,
|
||
};
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// material interface
|
||
//-----------------------------------------------------------------------------
|
||
abstract_class IMaterial
|
||
{
|
||
public:
|
||
// Get the name of the material. This is a full path to
|
||
// the vmt file starting from "hl2/materials" (or equivalent) without
|
||
// a file extension.
|
||
virtual const char * GetName() const = 0;
|
||
virtual const char * GetTextureGroupName() const = 0;
|
||
|
||
// Get the preferred size/bitDepth of a preview image of a material.
|
||
// This is the sort of image that you would use for a thumbnail view
|
||
// of a material, or in WorldCraft until it uses materials to render.
|
||
// separate this for the tools maybe
|
||
virtual PreviewImageRetVal_t GetPreviewImageProperties( int *width, int *height,
|
||
ImageFormat *imageFormat, bool* isTranslucent ) const = 0;
|
||
|
||
// Get a preview image at the specified width/height and bitDepth.
|
||
// Will do resampling if necessary.(not yet!!! :) )
|
||
// Will do color format conversion. (works now.)
|
||
virtual PreviewImageRetVal_t GetPreviewImage( unsigned char *data,
|
||
int width, int height,
|
||
ImageFormat imageFormat ) const = 0;
|
||
//
|
||
virtual int GetMappingWidth( ) = 0;
|
||
virtual int GetMappingHeight( ) = 0;
|
||
|
||
virtual int GetNumAnimationFrames( ) = 0;
|
||
|
||
// For material subrects (material pages). Offset(u,v) and scale(u,v) are normalized to texture.
|
||
virtual bool InMaterialPage( void ) = 0;
|
||
virtual void GetMaterialOffset( float *pOffset ) = 0;
|
||
virtual void GetMaterialScale( float *pScale ) = 0;
|
||
virtual IMaterial *GetMaterialPage( void ) = 0;
|
||
|
||
// find a vmt variable.
|
||
// This is how game code affects how a material is rendered.
|
||
// The game code must know about the params that are used by
|
||
// the shader for the material that it is trying to affect.
|
||
virtual IMaterialVar * FindVar( const char *varName, bool *found, bool complain = true ) = 0;
|
||
|
||
// The user never allocates or deallocates materials. Reference counting is
|
||
// used instead. Garbage collection is done upon a call to
|
||
// IMaterialSystem::UncacheUnusedMaterials.
|
||
virtual void IncrementReferenceCount( void ) = 0;
|
||
virtual void DecrementReferenceCount( void ) = 0;
|
||
|
||
inline void AddRef() { IncrementReferenceCount(); }
|
||
inline void Release() { DecrementReferenceCount(); }
|
||
|
||
// Each material is assigned a number that groups it with like materials
|
||
// for sorting in the application.
|
||
virtual int GetEnumerationID( void ) const = 0;
|
||
|
||
virtual void GetLowResColorSample( float s, float t, float *color ) const = 0;
|
||
|
||
// This computes the state snapshots for this material
|
||
virtual void RecomputeStateSnapshots() = 0;
|
||
|
||
// Are we translucent?
|
||
virtual bool IsTranslucent() = 0;
|
||
|
||
// Are we alphatested?
|
||
virtual bool IsAlphaTested() = 0;
|
||
|
||
// Are we vertex lit?
|
||
virtual bool IsVertexLit() = 0;
|
||
|
||
// Gets the vertex format
|
||
virtual VertexFormat_t GetVertexFormat() const = 0;
|
||
|
||
// returns true if this material uses a material proxy
|
||
virtual bool HasProxy( void ) const = 0;
|
||
|
||
virtual bool UsesEnvCubemap( void ) = 0;
|
||
|
||
virtual bool NeedsTangentSpace( void ) = 0;
|
||
|
||
virtual bool NeedsPowerOfTwoFrameBufferTexture( bool bCheckSpecificToThisFrame = true ) = 0;
|
||
virtual bool NeedsFullFrameBufferTexture( bool bCheckSpecificToThisFrame = true ) = 0;
|
||
|
||
// returns true if the shader doesn't do skinning itself and requires
|
||
// the data that is sent to it to be preskinned.
|
||
virtual bool NeedsSoftwareSkinning( void ) = 0;
|
||
|
||
// Apply constant color or alpha modulation
|
||
virtual void AlphaModulate( float alpha ) = 0;
|
||
virtual void ColorModulate( float r, float g, float b ) = 0;
|
||
|
||
// Material Var flags...
|
||
virtual void SetMaterialVarFlag( MaterialVarFlags_t flag, bool on ) = 0;
|
||
virtual bool GetMaterialVarFlag( MaterialVarFlags_t flag ) const = 0;
|
||
|
||
// Gets material reflectivity
|
||
virtual void GetReflectivity( Vector& reflect ) = 0;
|
||
|
||
// Gets material property flags
|
||
virtual bool GetPropertyFlag( MaterialPropertyTypes_t type ) = 0;
|
||
|
||
// Is the material visible from both sides?
|
||
virtual bool IsTwoSided() = 0;
|
||
|
||
// Sets the shader associated with the material
|
||
virtual void SetShader( const char *pShaderName ) = 0;
|
||
|
||
// Can't be const because the material might have to precache itself.
|
||
virtual int GetNumPasses( void ) = 0;
|
||
|
||
// Can't be const because the material might have to precache itself.
|
||
virtual int GetTextureMemoryBytes( void ) = 0;
|
||
|
||
// Meant to be used with materials created using CreateMaterial
|
||
// It updates the materials to reflect the current values stored in the material vars
|
||
virtual void Refresh() = 0;
|
||
|
||
// GR - returns true is material uses lightmap alpha for blending
|
||
virtual bool NeedsLightmapBlendAlpha( void ) = 0;
|
||
|
||
// returns true if the shader doesn't do lighting itself and requires
|
||
// the data that is sent to it to be prelighted
|
||
virtual bool NeedsSoftwareLighting( void ) = 0;
|
||
|
||
// Gets at the shader parameters
|
||
virtual int ShaderParamCount() const = 0;
|
||
virtual IMaterialVar **GetShaderParams( void ) = 0;
|
||
|
||
// Returns true if this is the error material you get back from IMaterialSystem::FindMaterial if
|
||
// the material can't be found.
|
||
virtual bool IsErrorMaterial() const = 0;
|
||
|
||
virtual void SetUseFixedFunctionBakedLighting( bool bEnable ) = 0;
|
||
|
||
// Gets the current alpha modulation
|
||
virtual float GetAlphaModulation() = 0;
|
||
virtual void GetColorModulation( float *r, float *g, float *b ) = 0;
|
||
|
||
// Is this translucent given a particular alpha modulation?
|
||
virtual bool IsTranslucentUnderModulation( float fAlphaModulation = 1.0f ) const = 0;
|
||
|
||
// fast find that stores the index of the found var in the string table in local cache
|
||
virtual IMaterialVar * FindVarFast( char const *pVarName, unsigned int *pToken ) = 0;
|
||
|
||
// Sets new VMT shader parameters for the material
|
||
virtual void SetShaderAndParams( KeyValues *pKeyValues ) = 0;
|
||
virtual const char * GetShaderName() const = 0;
|
||
|
||
virtual void DeleteIfUnreferenced() = 0;
|
||
|
||
virtual bool IsSpriteCard() = 0;
|
||
|
||
virtual void CallBindProxy( void *proxyData ) = 0;
|
||
|
||
virtual void RefreshPreservingMaterialVars() = 0;
|
||
|
||
virtual bool WasReloadedFromWhitelist() = 0;
|
||
};
|
||
|
||
|
||
inline bool IsErrorMaterial( IMaterial *pMat )
|
||
{
|
||
return !pMat || pMat->IsErrorMaterial();
|
||
}
|
||
|
||
|
||
//
|
||
// Vertex stream specifications
|
||
//
|
||
|
||
struct VertexStreamSpec_t
|
||
{
|
||
enum StreamSpec_t
|
||
{
|
||
STREAM_DEFAULT, // stream 0: with position, normal, etc.
|
||
STREAM_SPECULAR1, // stream 1: following specular vhv lighting
|
||
STREAM_FLEXDELTA, // stream 2: flex deltas
|
||
STREAM_MORPH, // stream 3: morph
|
||
STREAM_UNIQUE_A, // unique stream 4
|
||
STREAM_UNIQUE_B, // unique stream 5
|
||
STREAM_UNIQUE_C, // unique stream 6
|
||
STREAM_UNIQUE_D, // unique stream 7
|
||
STREAM_SUBDQUADS, // stream 8: quad buffer for subd's
|
||
};
|
||
|
||
enum
|
||
{
|
||
MAX_UNIQUE_STREAMS = 4
|
||
};
|
||
|
||
VertexFormatFlags_t iVertexDataElement;
|
||
StreamSpec_t iStreamSpec;
|
||
};
|
||
|
||
inline VertexStreamSpec_t * FindVertexStreamSpec( VertexFormat_t iElement, VertexStreamSpec_t *arrVertexStreamSpec )
|
||
{
|
||
for ( ; arrVertexStreamSpec &&
|
||
arrVertexStreamSpec->iVertexDataElement != VERTEX_FORMAT_UNKNOWN ;
|
||
++ arrVertexStreamSpec )
|
||
{
|
||
if ( arrVertexStreamSpec->iVertexDataElement == iElement )
|
||
return arrVertexStreamSpec;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
|
||
#endif // IMATERIAL_H
|