2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-09-23 16:56:39 +00:00

Merge pull request #464 from Laupetin/feature/material-iw3-t5

feat: add templated json material loading/dumping for IW3 and T5
This commit is contained in:
Jan
2025-07-08 23:33:40 +02:00
committed by GitHub
40 changed files with 3962 additions and 597 deletions

View File

@@ -21,6 +21,11 @@ namespace IW3
return result; return result;
} }
static constexpr uint32_t R_HashString(const char* string)
{
return R_HashString(string, 0u);
}
static PackedTexCoords Vec2PackTexCoords(const float (&in)[2]); static PackedTexCoords Vec2PackTexCoords(const float (&in)[2]);
static PackedUnitVec Vec3PackUnitVec(const float (&in)[3]); static PackedUnitVec Vec3PackUnitVec(const float (&in)[3]);
static GfxColor Vec4PackGfxColor(const float (&in)[4]); static GfxColor Vec4PackGfxColor(const float (&in)[4]);

View File

@@ -566,7 +566,8 @@ namespace IW3
GFXS_BLEND_INVDESTALPHA = 0x8, GFXS_BLEND_INVDESTALPHA = 0x8,
GFXS_BLEND_DESTCOLOR = 0x9, GFXS_BLEND_DESTCOLOR = 0x9,
GFXS_BLEND_INVDESTCOLOR = 0xA, GFXS_BLEND_INVDESTCOLOR = 0xA,
GFXS_BLEND_MASK = 0xF,
GFXS_BLEND_COUNT
}; };
enum GfxBlendOp enum GfxBlendOp
@@ -577,7 +578,40 @@ namespace IW3
GFXS_BLENDOP_REVSUBTRACT = 0x3, GFXS_BLENDOP_REVSUBTRACT = 0x3,
GFXS_BLENDOP_MIN = 0x4, GFXS_BLENDOP_MIN = 0x4,
GFXS_BLENDOP_MAX = 0x5, GFXS_BLENDOP_MAX = 0x5,
GFXS_BLENDOP_MASK = 0x7,
GFXS_BLENDOP_COUNT
};
enum GfxAlphaTest_e
{
GFXS_ALPHA_TEST_GT_0 = 1,
GFXS_ALPHA_TEST_LT_128 = 2,
GFXS_ALPHA_TEST_GE_128 = 3,
GFXS_ALPHA_TEST_COUNT
};
enum GfxCullFace_e
{
GFXS_CULL_NONE = 1,
GFXS_CULL_BACK = 2,
GFXS_CULL_FRONT = 3,
};
enum GfxDepthTest_e
{
GFXS_DEPTHTEST_ALWAYS = 0,
GFXS_DEPTHTEST_LESS = 1,
GFXS_DEPTHTEST_EQUAL = 2,
GFXS_DEPTHTEST_LESSEQUAL = 3
};
enum GfxPolygonOffset_e
{
GFXS_POLYGON_OFFSET_0 = 0,
GFXS_POLYGON_OFFSET_1 = 1,
GFXS_POLYGON_OFFSET_2 = 2,
GFXS_POLYGON_OFFSET_SHADOWMAP = 3
}; };
enum GfxStencilOp enum GfxStencilOp
@@ -589,10 +623,19 @@ namespace IW3
GFXS_STENCILOP_DECRSAT = 0x4, GFXS_STENCILOP_DECRSAT = 0x4,
GFXS_STENCILOP_INVERT = 0x5, GFXS_STENCILOP_INVERT = 0x5,
GFXS_STENCILOP_INCR = 0x6, GFXS_STENCILOP_INCR = 0x6,
GFXS_STENCILOP_DECR = 0x7, GFXS_STENCILOP_DECR = 0x7
};
GFXS_STENCILOP_COUNT, enum GfxStencilFunc
GFXS_STENCILOP_MASK = 0x7 {
GFXS_STENCILFUNC_NEVER = 0x0,
GFXS_STENCILFUNC_LESS = 0x1,
GFXS_STENCILFUNC_EQUAL = 0x2,
GFXS_STENCILFUNC_LESSEQUAL = 0x3,
GFXS_STENCILFUNC_GREATER = 0x4,
GFXS_STENCILFUNC_NOTEQUAL = 0x5,
GFXS_STENCILFUNC_GREATEREQUAL = 0x6,
GFXS_STENCILFUNC_ALWAYS = 0x7
}; };
enum GfxStateBitsEnum : unsigned int enum GfxStateBitsEnum : unsigned int
@@ -613,10 +656,10 @@ namespace IW3
GFXS0_ATEST_GE_128 = 0x3000, GFXS0_ATEST_GE_128 = 0x3000,
GFXS0_ATEST_MASK = 0x3000, GFXS0_ATEST_MASK = 0x3000,
GFXS0_CULL_SHIFT = 0xE,
GFXS0_CULL_NONE = 0x4000, GFXS0_CULL_NONE = 0x4000,
GFXS0_CULL_BACK = 0x8000, GFXS0_CULL_BACK = 0x8000,
GFXS0_CULL_FRONT = 0xC000, GFXS0_CULL_FRONT = 0xC000,
GFXS0_CULL_SHIFT = 0xE,
GFXS0_CULL_MASK = 0xC000, GFXS0_CULL_MASK = 0xC000,
GFXS0_SRCBLEND_ALPHA_SHIFT = 0x10, GFXS0_SRCBLEND_ALPHA_SHIFT = 0x10,
@@ -638,18 +681,18 @@ namespace IW3
GFXS1_DEPTHWRITE = 0x1, GFXS1_DEPTHWRITE = 0x1,
GFXS1_DEPTHTEST_DISABLE = 0x2, GFXS1_DEPTHTEST_DISABLE = 0x2,
GFXS1_DEPTHTEST_SHIFT = 0x2,
GFXS1_DEPTHTEST_ALWAYS = 0x0, GFXS1_DEPTHTEST_ALWAYS = 0x0,
GFXS1_DEPTHTEST_LESS = 0x4, GFXS1_DEPTHTEST_LESS = 0x4,
GFXS1_DEPTHTEST_EQUAL = 0x8, GFXS1_DEPTHTEST_EQUAL = 0x8,
GFXS1_DEPTHTEST_LESSEQUAL = 0xC, GFXS1_DEPTHTEST_LESSEQUAL = 0xC,
GFXS1_DEPTHTEST_SHIFT = 0x2,
GFXS1_DEPTHTEST_MASK = 0xC, GFXS1_DEPTHTEST_MASK = 0xC,
GFXS1_POLYGON_OFFSET_SHIFT = 0x4,
GFXS1_POLYGON_OFFSET_0 = 0x0, GFXS1_POLYGON_OFFSET_0 = 0x0,
GFXS1_POLYGON_OFFSET_1 = 0x10, GFXS1_POLYGON_OFFSET_1 = 0x10,
GFXS1_POLYGON_OFFSET_2 = 0x20, GFXS1_POLYGON_OFFSET_2 = 0x20,
GFXS1_POLYGON_OFFSET_SHADOWMAP = 0x30, GFXS1_POLYGON_OFFSET_SHADOWMAP = 0x30,
GFXS1_POLYGON_OFFSET_SHIFT = 0x4,
GFXS1_POLYGON_OFFSET_MASK = 0x30, GFXS1_POLYGON_OFFSET_MASK = 0x30,
GFXS1_STENCIL_FRONT_ENABLE = 0x40, GFXS1_STENCIL_FRONT_ENABLE = 0x40,
@@ -672,16 +715,61 @@ namespace IW3
GFXS1_STENCILOP_FRONTBACK_MASK = 0x1FF1FF00, GFXS1_STENCILOP_FRONTBACK_MASK = 0x1FF1FF00,
}; };
struct GfxStateBitsLoadBitsStructured
{
// Byte 0
unsigned int srcBlendRgb : 4; // 0-3
unsigned int dstBlendRgb : 4; // 4-7
unsigned int blendOpRgb : 3; // 8-10
unsigned int alphaTestDisabled : 1; // 11
unsigned int alphaTest : 2; // 12-13
unsigned int cullFace : 2; // 14-15
unsigned int srcBlendAlpha : 4; // 16-19
unsigned int dstBlendAlpha : 4; // 20-23
unsigned int blendOpAlpha : 3; // 24-26
unsigned int colorWriteRgb : 1; // 27
unsigned int colorWriteAlpha : 1; // 28
unsigned int unused1 : 2; // 29-30
unsigned int polymodeLine : 1; // 31
// Byte 1
unsigned int depthWrite : 1; // 0
unsigned int depthTestDisabled : 1; // 1
unsigned int depthTest : 2; // 2-3
unsigned int polygonOffset : 2; // 4-5
unsigned int stencilFrontEnabled : 1; // 6
unsigned int stencilBackEnabled : 1; // 7
unsigned int stencilFrontPass : 3; // 8-10
unsigned int stencilFrontFail : 3; // 11-13
unsigned int stencilFrontZFail : 3; // 14-16
unsigned int stencilFrontFunc : 3; // 17-19
unsigned int stencilBackPass : 3; // 20-22
unsigned int stencilBackFail : 3; // 23-25
unsigned int stencilBackZFail : 3; // 26-28
unsigned int stencilBackFunc : 3; // 29-31
};
union GfxStateBitsLoadBits
{
unsigned int raw[2];
GfxStateBitsLoadBitsStructured structured;
};
#ifndef __zonecodegenerator
static_assert(sizeof(GfxStateBitsLoadBits) == 8);
static_assert(sizeof(GfxStateBitsLoadBitsStructured) == 8);
#endif
struct GfxStateBits struct GfxStateBits
{ {
unsigned int loadBits[2]; GfxStateBitsLoadBits loadBits;
}; };
struct type_align(16) MaterialConstantDef struct type_align(16) MaterialConstantDef
{ {
unsigned int nameHash; unsigned int nameHash;
char name[12]; char name[12];
float literal[4]; vec4_t literal;
}; };
struct complex_s struct complex_s
@@ -718,6 +806,26 @@ namespace IW3
water_t* water; water_t* water;
}; };
enum TextureFilter
{
TEXTURE_FILTER_DISABLED = 0x0,
TEXTURE_FILTER_NEAREST = 0x1,
TEXTURE_FILTER_LINEAR = 0x2,
TEXTURE_FILTER_ANISO2X = 0x3,
TEXTURE_FILTER_ANISO4X = 0x4,
TEXTURE_FILTER_COUNT
};
enum SamplerStateBitsMipMap_e
{
SAMPLER_MIPMAP_ENUM_DISABLED,
SAMPLER_MIPMAP_ENUM_NEAREST,
SAMPLER_MIPMAP_ENUM_LINEAR,
SAMPLER_MIPMAP_ENUM_COUNT
};
enum SamplerStateBits_e enum SamplerStateBits_e
{ {
SAMPLER_FILTER_SHIFT = 0x0, SAMPLER_FILTER_SHIFT = 0x0,
@@ -743,12 +851,25 @@ namespace IW3
SAMPLER_CLAMP_MASK = 0xE0, SAMPLER_CLAMP_MASK = 0xE0,
}; };
struct MaterialTextureDefSamplerState
{
unsigned char filter : 3;
unsigned char mipMap : 2;
unsigned char clampU : 1;
unsigned char clampV : 1;
unsigned char clampW : 1;
};
#ifndef __zonecodegenerator
static_assert(sizeof(MaterialTextureDefSamplerState) == 1u);
#endif
struct MaterialTextureDef struct MaterialTextureDef
{ {
unsigned int nameHash; unsigned int nameHash;
char nameStart; char nameStart;
char nameEnd; char nameEnd;
unsigned char samplerState; // SamplerStateBits_e MaterialTextureDefSamplerState samplerState; // SamplerStateBits_e
unsigned char semantic; // TextureSemantic unsigned char semantic; // TextureSemantic
MaterialTextureDefInfo u; MaterialTextureDefInfo u;
}; };
@@ -842,8 +963,9 @@ namespace IW3
CAMERA_REGION_LIT = 0x0, CAMERA_REGION_LIT = 0x0,
CAMERA_REGION_DECAL = 0x1, CAMERA_REGION_DECAL = 0x1,
CAMERA_REGION_EMISSIVE = 0x2, CAMERA_REGION_EMISSIVE = 0x2,
CAMERA_REGION_COUNT = 0x3,
CAMERA_REGION_NONE = 0x3, CAMERA_REGION_COUNT,
CAMERA_REGION_NONE = CAMERA_REGION_COUNT,
}; };
enum MaterialStateFlags enum MaterialStateFlags

View File

@@ -11,6 +11,21 @@ namespace T5
static int Com_HashString(const char* str); static int Com_HashString(const char* str);
static int Com_HashString(const char* str, int len); static int Com_HashString(const char* str, int len);
static constexpr uint32_t R_HashString(const char* str, uint32_t hash)
{
for (const auto* pos = str; *pos; pos++)
{
hash = 33 * hash ^ (*pos | 0x20);
}
return hash;
}
static constexpr uint32_t R_HashString(const char* string)
{
return R_HashString(string, 0u);
}
static PackedTexCoords Vec2PackTexCoords(const float (&in)[2]); static PackedTexCoords Vec2PackTexCoords(const float (&in)[2]);
static PackedUnitVec Vec3PackUnitVec(const float (&in)[3]); static PackedUnitVec Vec3PackUnitVec(const float (&in)[3]);
static GfxColor Vec4PackGfxColor(const float (&in)[4]); static GfxColor Vec4PackGfxColor(const float (&in)[4]);

View File

@@ -739,14 +739,30 @@ namespace T5
gcc_align32(8) uint64_t packed; gcc_align32(8) uint64_t packed;
}; };
enum MaterialGameFlags
{
MTL_GAMEFLAG_1 = 0x1,
MTL_GAMEFLAG_2 = 0x2,
MTL_GAMEFLAG_4 = 0x4,
MTL_GAMEFLAG_8 = 0x8,
MTL_GAMEFLAG_10 = 0x10,
MTL_GAMEFLAG_20 = 0x20,
// Probably, seems to be this in T5
MTL_GAMEFLAG_CASTS_SHADOW = 0x40,
MTL_GAMEFLAG_80 = 0x80,
MTL_GAMEFLAG_100 = 0x100,
MTL_GAMEFLAG_200 = 0x200,
};
struct MaterialInfo struct MaterialInfo
{ {
const char* name; const char* name;
unsigned int gameFlags; unsigned int gameFlags;
char pad; char pad;
char sortKey; unsigned char sortKey;
char textureAtlasRowCount; unsigned char textureAtlasRowCount;
char textureAtlasColumnCount; unsigned char textureAtlasColumnCount;
GfxDrawSurf drawSurf; GfxDrawSurf drawSurf;
unsigned int surfaceTypeBits; unsigned int surfaceTypeBits;
unsigned int layeredSurfaceTypes; unsigned int layeredSurfaceTypes;
@@ -787,14 +803,47 @@ namespace T5
water_t* water; water_t* water;
}; };
enum TextureFilter
{
TEXTURE_FILTER_DISABLED = 0x0,
TEXTURE_FILTER_NEAREST = 0x1,
TEXTURE_FILTER_LINEAR = 0x2,
TEXTURE_FILTER_ANISO2X = 0x3,
TEXTURE_FILTER_ANISO4X = 0x4,
TEXTURE_FILTER_COUNT
};
enum SamplerStateBitsMipMap_e
{
SAMPLER_MIPMAP_ENUM_DISABLED,
SAMPLER_MIPMAP_ENUM_NEAREST,
SAMPLER_MIPMAP_ENUM_LINEAR,
SAMPLER_MIPMAP_ENUM_COUNT
};
struct MaterialTextureDefSamplerState
{
unsigned char filter : 3;
unsigned char mipMap : 2;
unsigned char clampU : 1;
unsigned char clampV : 1;
unsigned char clampW : 1;
};
#ifndef __zonecodegenerator
static_assert(sizeof(MaterialTextureDefSamplerState) == 1u);
#endif
struct MaterialTextureDef struct MaterialTextureDef
{ {
unsigned int nameHash; unsigned int nameHash;
char nameStart; char nameStart;
char nameEnd; char nameEnd;
char samplerState; MaterialTextureDefSamplerState samplerState;
unsigned char semantic; // TextureSemantic unsigned char semantic; // TextureSemantic
char isMatureContent; bool isMatureContent;
char pad[3]; char pad[3];
MaterialTextureDefInfo u; MaterialTextureDefInfo u;
}; };
@@ -803,7 +852,96 @@ namespace T5
{ {
unsigned int nameHash; unsigned int nameHash;
char name[12]; char name[12];
float literal[4]; vec4_t literal;
};
enum GfxBlend : unsigned int
{
GFXS_BLEND_DISABLED = 0x0,
GFXS_BLEND_ZERO = 0x1,
GFXS_BLEND_ONE = 0x2,
GFXS_BLEND_SRCCOLOR = 0x3,
GFXS_BLEND_INVSRCCOLOR = 0x4,
GFXS_BLEND_SRCALPHA = 0x5,
GFXS_BLEND_INVSRCALPHA = 0x6,
GFXS_BLEND_DESTALPHA = 0x7,
GFXS_BLEND_INVDESTALPHA = 0x8,
GFXS_BLEND_DESTCOLOR = 0x9,
GFXS_BLEND_INVDESTCOLOR = 0xA,
GFXS_BLEND_MASK = 0xF,
};
enum GfxBlendOp : unsigned int
{
GFXS_BLENDOP_DISABLED = 0x0,
GFXS_BLENDOP_ADD = 0x1,
GFXS_BLENDOP_SUBTRACT = 0x2,
GFXS_BLENDOP_REVSUBTRACT = 0x3,
GFXS_BLENDOP_MIN = 0x4,
GFXS_BLENDOP_MAX = 0x5,
GFXS_BLENDOP_MASK = 0x7,
};
enum GfxAlphaTest_e
{
GFXS_ALPHA_TEST_GT_0 = 1,
GFXS_ALPHA_TEST_GE_255 = 2,
GFXS_ALPHA_TEST_GE_128 = 3,
GFXS_ALPHA_TEST_COUNT
};
enum GfxCullFace_e
{
GFXS_CULL_NONE = 1,
GFXS_CULL_BACK = 2,
GFXS_CULL_FRONT = 3,
};
enum GfxDepthTest_e
{
GFXS_DEPTHTEST_ALWAYS = 0,
GFXS_DEPTHTEST_LESS = 1,
GFXS_DEPTHTEST_EQUAL = 2,
GFXS_DEPTHTEST_LESSEQUAL = 3
};
enum GfxPolygonOffset_e
{
GFXS_POLYGON_OFFSET_0 = 0,
GFXS_POLYGON_OFFSET_1 = 1,
GFXS_POLYGON_OFFSET_2 = 2,
GFXS_POLYGON_OFFSET_SHADOWMAP = 3
};
enum GfxStencilOp : unsigned int
{
GFXS_STENCILOP_KEEP = 0x0,
GFXS_STENCILOP_ZERO = 0x1,
GFXS_STENCILOP_REPLACE = 0x2,
GFXS_STENCILOP_INCRSAT = 0x3,
GFXS_STENCILOP_DECRSAT = 0x4,
GFXS_STENCILOP_INVERT = 0x5,
GFXS_STENCILOP_INCR = 0x6,
GFXS_STENCILOP_DECR = 0x7,
GFXS_STENCILOP_COUNT,
GFXS_STENCILOP_MASK = 0x7
};
enum GfxStencilFunc : unsigned int
{
GFXS_STENCILFUNC_NEVER = 0x0,
GFXS_STENCILFUNC_LESS = 0x1,
GFXS_STENCILFUNC_EQUAL = 0x2,
GFXS_STENCILFUNC_LESSEQUAL = 0x3,
GFXS_STENCILFUNC_GREATER = 0x4,
GFXS_STENCILFUNC_NOTEQUAL = 0x5,
GFXS_STENCILFUNC_GREATEREQUAL = 0x6,
GFXS_STENCILFUNC_ALWAYS = 0x7,
GFXS_STENCILFUNC_COUNT,
GFXS_STENCILFUNC_MASK = 0x7
}; };
enum GfxStateBitsEnum : unsigned int enum GfxStateBitsEnum : unsigned int
@@ -868,9 +1006,64 @@ namespace T5
GFXS1_STENCILOP_FRONTBACK_MASK = 0x1FF1FF00, GFXS1_STENCILOP_FRONTBACK_MASK = 0x1FF1FF00,
}; };
struct GfxStateBitsLoadBitsStructured
{
// Byte 0
unsigned int srcBlendRgb : 4; // 0-3
unsigned int dstBlendRgb : 4; // 4-7
unsigned int blendOpRgb : 3; // 8-10
unsigned int alphaTestDisabled : 1; // 11
unsigned int alphaTest : 2; // 12-13
unsigned int cullFace : 2; // 14-15
unsigned int srcBlendAlpha : 4; // 16-19
unsigned int dstBlendAlpha : 4; // 20-23
unsigned int blendOpAlpha : 3; // 24-26
unsigned int colorWriteRgb : 1; // 27
unsigned int colorWriteAlpha : 1; // 28
unsigned int unused0 : 2; // 29-30
unsigned int polymodeLine : 1; // 31
// Byte 1
unsigned int depthWrite : 1; // 0
unsigned int depthTestDisabled : 1; // 1
unsigned int depthTest : 2; // 2-3
unsigned int polygonOffset : 2; // 4-5
unsigned int stencilFrontEnabled : 1; // 6
unsigned int stencilBackEnabled : 1; // 7
unsigned int stencilFrontPass : 3; // 8-10
unsigned int stencilFrontFail : 3; // 11-13
unsigned int stencilFrontZFail : 3; // 14-16
unsigned int stencilFrontFunc : 3; // 17-19
unsigned int stencilBackPass : 3; // 20-22
unsigned int stencilBackFail : 3; // 23-25
unsigned int stencilBackZFail : 3; // 26-28
unsigned int stencilBackFunc : 3; // 29-31
};
union GfxStateBitsLoadBits
{
unsigned int raw[2];
GfxStateBitsLoadBitsStructured structured;
};
#ifndef __zonecodegenerator
static_assert(sizeof(GfxStateBitsLoadBits) == 8);
static_assert(sizeof(GfxStateBitsLoadBitsStructured) == 8);
#endif
struct GfxStateBits struct GfxStateBits
{ {
unsigned int loadBits[2]; GfxStateBitsLoadBits loadBits;
};
enum GfxCameraRegionType
{
CAMERA_REGION_LIT = 0x0,
CAMERA_REGION_DECAL = 0x1,
CAMERA_REGION_EMISSIVE = 0x2,
CAMERA_REGION_COUNT,
CAMERA_REGION_NONE = CAMERA_REGION_COUNT,
}; };
struct Material struct Material
@@ -880,8 +1073,8 @@ namespace T5
unsigned char textureCount; unsigned char textureCount;
unsigned char constantCount; unsigned char constantCount;
unsigned char stateBitsCount; unsigned char stateBitsCount;
char stateFlags; unsigned char stateFlags;
char cameraRegion; unsigned char cameraRegion;
unsigned char maxStreamedMips; unsigned char maxStreamedMips;
MaterialTechniqueSet* techniqueSet; MaterialTechniqueSet* techniqueSet;
MaterialTextureDef* textureTable; MaterialTextureDef* textureTable;

View File

@@ -700,6 +700,8 @@ namespace T6
MTL_GAMEFLAG_400 = 0x400, MTL_GAMEFLAG_400 = 0x400,
MTL_GAMEFLAG_800 = 0x800, MTL_GAMEFLAG_800 = 0x800,
MTL_GAMEFLAG_1000 = 0x1000, MTL_GAMEFLAG_1000 = 0x1000,
MTL_GAMEFLAG_2000 = 0x2000,
MTL_GAMEFLAG_4000 = 0x4000,
}; };
struct type_align32(8) MaterialInfo struct type_align32(8) MaterialInfo

View File

@@ -1,13 +1,19 @@
#options GAME (IW4, IW5, T6) #options GAME (IW3, IW4, IW5, T5, T6)
#filename "Game/" + GAME + "/Material/JsonMaterial" + GAME + ".h" #filename "Game/" + GAME + "/Material/JsonMaterial" + GAME + ".h"
#if GAME == "IW4" #if GAME == "IW3"
#define FEATURE_IW3
#define HAS_WATER
#elif GAME == "IW4"
#define FEATURE_IW4 #define FEATURE_IW4
#define HAS_WATER #define HAS_WATER
#elif GAME == "IW5" #elif GAME == "IW5"
#define FEATURE_IW5 #define FEATURE_IW5
#define HAS_WATER #define HAS_WATER
#elif GAME == "T5"
#define FEATURE_T5
#define HAS_WATER
#elif GAME == "T6" #elif GAME == "T6"
#define FEATURE_T6 #define FEATURE_T6
#endif #endif
@@ -75,8 +81,10 @@ namespace GAME
INVALID, INVALID,
DISABLED, DISABLED,
GT0, GT0,
#if defined(FEATURE_IW4) || defined(FEATURE_IW5) #if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5)
LT128, LT128,
#elif defined(FEATURE_T5)
GE255,
#endif #endif
GE128 GE128
}; };
@@ -85,8 +93,10 @@ namespace GAME
{JsonAlphaTest::INVALID, nullptr }, {JsonAlphaTest::INVALID, nullptr },
{JsonAlphaTest::DISABLED, "disabled"}, {JsonAlphaTest::DISABLED, "disabled"},
{JsonAlphaTest::GT0, "gt0" }, {JsonAlphaTest::GT0, "gt0" },
#if defined(FEATURE_IW4) || defined(FEATURE_IW5) #if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5)
{JsonAlphaTest::LT128, "lt128" }, {JsonAlphaTest::LT128, "lt128" },
#elif defined(FEATURE_T5)
{JsonAlphaTest::GE255, "ge255" },
#endif #endif
{JsonAlphaTest::GE128, "ge128" } {JsonAlphaTest::GE128, "ge128" }
}); });
@@ -208,7 +218,7 @@ namespace GAME
std::optional<std::string> name; std::optional<std::string> name;
std::optional<std::string> nameFragment; std::optional<std::string> nameFragment;
std::optional<unsigned> nameHash; std::optional<unsigned> nameHash;
std::vector<float> literal; std::array<float, 4> literal;
}; };
inline void to_json(nlohmann::json& out, const JsonConstant& in) inline void to_json(nlohmann::json& out, const JsonConstant& in)
@@ -315,35 +325,31 @@ namespace GAME
#endif #endif
NLOHMANN_JSON_SERIALIZE_ENUM(TextureSemantic, { NLOHMANN_JSON_SERIALIZE_ENUM(TextureSemantic, {
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
{TS_2D, "2D" }, {TS_2D, "2D" },
{TS_FUNCTION, "function" }, {TS_FUNCTION, "function" },
{TS_COLOR_MAP, "colorMap" }, {TS_COLOR_MAP, "colorMap" },
#if defined(FEATURE_IW3) || defined(FEATURE_T5) || defined(FEATURE_T6)
{TS_UNUSED_1, "unused1" },
#else
{TS_DETAIL_MAP, "detailMap" }, {TS_DETAIL_MAP, "detailMap" },
#endif
{TS_UNUSED_2, "unused2" }, {TS_UNUSED_2, "unused2" },
{TS_NORMAL_MAP, "normalMap" }, {TS_NORMAL_MAP, "normalMap" },
{TS_UNUSED_3, "unused3" }, {TS_UNUSED_3, "unused3" },
{TS_UNUSED_4, "unused4" }, {TS_UNUSED_4, "unused4" },
{TS_SPECULAR_MAP, "specularMap" }, {TS_SPECULAR_MAP, "specularMap" },
{TS_UNUSED_5, "unused5" }, {TS_UNUSED_5, "unused5" },
#ifdef FEATURE_T6
{TS_OCCLUSION_MAP, "occlusionMap" },
#endif
{TS_UNUSED_6, "unused6" }, {TS_UNUSED_6, "unused6" },
#if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5) || defined(FEATURE_T5)
{TS_WATER_MAP, "waterMap" }, {TS_WATER_MAP, "waterMap" },
#endif
#ifdef FEATURE_IW5 #ifdef FEATURE_IW5
{TS_DISPLACEMENT_MAP, "displacementMap"}, {TS_DISPLACEMENT_MAP, "displacementMap"},
#endif #endif
#elif defined(FEATURE_T6) #if defined(FEATURE_T5) || defined(FEATURE_T6)
{TS_2D, "2D" },
{TS_FUNCTION, "function" },
{TS_COLOR_MAP, "colorMap" },
{TS_UNUSED_1, "unused1" },
{TS_UNUSED_2, "unused2" },
{TS_NORMAL_MAP, "normalMap" },
{TS_UNUSED_3, "unused3" },
{TS_UNUSED_4, "unused4" },
{TS_SPECULAR_MAP, "specularMap" },
{TS_UNUSED_5, "unused5" },
{TS_OCCLUSION_MAP, "occlusionMap"},
{TS_UNUSED_6, "unused6" },
{TS_COLOR0_MAP, "color0Map" }, {TS_COLOR0_MAP, "color0Map" },
{TS_COLOR1_MAP, "color1Map" }, {TS_COLOR1_MAP, "color1Map" },
{TS_COLOR2_MAP, "color2Map" }, {TS_COLOR2_MAP, "color2Map" },
@@ -372,7 +378,7 @@ namespace GAME
std::optional<std::string> nameStart; std::optional<std::string> nameStart;
std::optional<std::string> nameEnd; std::optional<std::string> nameEnd;
TextureSemantic semantic; TextureSemantic semantic;
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
bool isMatureContent; bool isMatureContent;
#endif #endif
JsonSamplerState samplerState; JsonSamplerState samplerState;
@@ -396,7 +402,7 @@ namespace GAME
} }
out["semantic"] = in.semantic; out["semantic"] = in.semantic;
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
out["isMatureContent"] = in.isMatureContent; out["isMatureContent"] = in.isMatureContent;
#endif #endif
out["samplerState"] = in.samplerState; out["samplerState"] = in.samplerState;
@@ -413,7 +419,7 @@ namespace GAME
optional_from_json(in, "nameStart", out.nameStart); optional_from_json(in, "nameStart", out.nameStart);
optional_from_json(in, "nameEnd", out.nameEnd); optional_from_json(in, "nameEnd", out.nameEnd);
in.at("semantic").get_to(out.semantic); in.at("semantic").get_to(out.semantic);
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
in.at("isMatureContent").get_to(out.isMatureContent); in.at("isMatureContent").get_to(out.isMatureContent);
#endif #endif
in.at("samplerState").get_to(out.samplerState); in.at("samplerState").get_to(out.samplerState);
@@ -437,36 +443,43 @@ namespace GAME
); );
NLOHMANN_JSON_SERIALIZE_ENUM(MaterialGameFlags, { NLOHMANN_JSON_SERIALIZE_ENUM(MaterialGameFlags, {
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
{MTL_GAMEFLAG_1, "1" },
{MTL_GAMEFLAG_2, "2" },
{MTL_GAMEFLAG_4, "4" },
{MTL_GAMEFLAG_8, "8" },
{MTL_GAMEFLAG_10, "10" },
{MTL_GAMEFLAG_20, "20" },
{MTL_GAMEFLAG_40, "40" },
{MTL_GAMEFLAG_80, "80" },
#elif defined(FEATURE_T6)
{MTL_GAMEFLAG_1, "1" }, {MTL_GAMEFLAG_1, "1" },
{MTL_GAMEFLAG_2, "2" }, {MTL_GAMEFLAG_2, "2" },
#ifdef FEATURE_T6
{MTL_GAMEFLAG_NO_MARKS, "NO_MARKS" }, {MTL_GAMEFLAG_NO_MARKS, "NO_MARKS" },
{MTL_GAMEFLAG_NO_MARKS, "4" }, {MTL_GAMEFLAG_NO_MARKS, "4" },
#else
{MTL_GAMEFLAG_4, "4" },
#endif
{MTL_GAMEFLAG_8, "8" }, {MTL_GAMEFLAG_8, "8" },
{MTL_GAMEFLAG_10, "10" }, {MTL_GAMEFLAG_10, "10" },
{MTL_GAMEFLAG_20, "20" }, {MTL_GAMEFLAG_20, "20" },
#if defined(FEATURE_IW3) || defined(FEATURE_T5) || defined(FEATURE_T6)
{MTL_GAMEFLAG_CASTS_SHADOW, "CASTS_SHADOW"}, {MTL_GAMEFLAG_CASTS_SHADOW, "CASTS_SHADOW"},
{MTL_GAMEFLAG_CASTS_SHADOW, "40" }, {MTL_GAMEFLAG_CASTS_SHADOW, "40" },
#else
{MTL_GAMEFLAG_40, "40" },
#endif
{MTL_GAMEFLAG_80, "80" }, {MTL_GAMEFLAG_80, "80" },
#if defined(FEATURE_T5) || defined(FEATURE_T6)
{MTL_GAMEFLAG_100, "100" }, {MTL_GAMEFLAG_100, "100" },
{MTL_GAMEFLAG_200, "200" }, {MTL_GAMEFLAG_200, "200" },
#if defined(FEATURE_T6)
{MTL_GAMEFLAG_400, "400" }, {MTL_GAMEFLAG_400, "400" },
{MTL_GAMEFLAG_800, "800" }, {MTL_GAMEFLAG_800, "800" },
{MTL_GAMEFLAG_1000, "1000" }, {MTL_GAMEFLAG_1000, "1000" },
{MTL_GAMEFLAG_2000, "2000" },
{MTL_GAMEFLAG_4000, "4000" },
#endif
#endif #endif
}); });
NLOHMANN_JSON_SERIALIZE_ENUM(GfxCameraRegionType, { NLOHMANN_JSON_SERIALIZE_ENUM(GfxCameraRegionType, {
#if defined(FEATURE_IW4) || defined(FEATURE_IW5) #if defined(FEATURE_IW3) || defined(FEATURE_T5)
{CAMERA_REGION_LIT, "lit" },
{CAMERA_REGION_DECAL, "decal" },
{CAMERA_REGION_EMISSIVE, "emissive" },
#elif defined(FEATURE_IW4) || defined(FEATURE_IW5)
{CAMERA_REGION_LIT_OPAQUE, "litOpaque" }, {CAMERA_REGION_LIT_OPAQUE, "litOpaque" },
{CAMERA_REGION_LIT_TRANS, "litTrans" }, {CAMERA_REGION_LIT_TRANS, "litTrans" },
{CAMERA_REGION_EMISSIVE, "emissive" }, {CAMERA_REGION_EMISSIVE, "emissive" },
@@ -474,7 +487,6 @@ namespace GAME
#ifdef FEATURE_IW5 #ifdef FEATURE_IW5
{CAMERA_REGION_LIGHT_MAP_OPAQUE, "lightMapOpaque"}, {CAMERA_REGION_LIGHT_MAP_OPAQUE, "lightMapOpaque"},
#endif #endif
{CAMERA_REGION_NONE, "none" },
#elif defined(FEATURE_T6) #elif defined(FEATURE_T6)
{CAMERA_REGION_LIT_OPAQUE, "litOpaque" }, {CAMERA_REGION_LIT_OPAQUE, "litOpaque" },
{CAMERA_REGION_LIT_TRANS, "litTrans" }, {CAMERA_REGION_LIT_TRANS, "litTrans" },
@@ -486,20 +498,20 @@ namespace GAME
{CAMERA_REGION_DEPTH_HACK, "depthHack" }, {CAMERA_REGION_DEPTH_HACK, "depthHack" },
{CAMERA_REGION_UNUSED, "unused" }, {CAMERA_REGION_UNUSED, "unused" },
{CAMERA_REGION_SONAR, "sonar" }, {CAMERA_REGION_SONAR, "sonar" },
{CAMERA_REGION_NONE, "none" },
#endif #endif
{CAMERA_REGION_NONE, "none" },
}); });
class JsonMaterial class JsonMaterial
{ {
public: public:
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
unsigned layeredSurfaceTypes; unsigned layeredSurfaceTypes;
unsigned hashIndex; #if defined(FEATURE_T6)
unsigned surfaceFlags; unsigned surfaceFlags;
unsigned contents; unsigned contents;
uint8_t probeMipBits;
std::optional<std::string> thermalMaterial; std::optional<std::string> thermalMaterial;
#endif
#endif #endif
std::vector<MaterialGameFlags> gameFlags; std::vector<MaterialGameFlags> gameFlags;
unsigned sortKey; unsigned sortKey;
@@ -516,13 +528,13 @@ namespace GAME
NLOHMANN_DEFINE_TYPE_EXTENSION( NLOHMANN_DEFINE_TYPE_EXTENSION(
JsonMaterial, JsonMaterial,
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
layeredSurfaceTypes, layeredSurfaceTypes,
hashIndex, #if defined(FEATURE_T6)
surfaceFlags, surfaceFlags,
contents, contents,
probeMipBits,
thermalMaterial, thermalMaterial,
#endif
#endif #endif
gameFlags, gameFlags,
sortKey, sortKey,

View File

@@ -0,0 +1,54 @@
#include "LoaderMaterialIW3.h"
#include "Game/IW3/IW3.h"
#include "Game/IW3/Material/JsonMaterialLoaderIW3.h"
#include "Material/MaterialCommon.h"
#include <format>
#include <iostream>
using namespace IW3;
namespace
{
class MaterialLoader final : public AssetCreator<AssetMaterial>
{
public:
MaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(material::GetFileNameForAssetName(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* material = m_memory.Alloc<Material>();
material->info.name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetMaterial> registration(assetName, material);
if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration))
{
std::cerr << std::format("Failed to load material \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace IW3
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MaterialLoader>(memory, searchPath);
}
} // namespace IW3

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW3/IW3.h"
#include "Gdt/IGdtQueryable.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
namespace IW3
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW3

View File

@@ -5,6 +5,7 @@
#include "Game/IW3/IW3.h" #include "Game/IW3/IW3.h"
#include "Image/AssetLoaderImageIW3.h" #include "Image/AssetLoaderImageIW3.h"
#include "Localize/AssetLoaderLocalizeIW3.h" #include "Localize/AssetLoaderLocalizeIW3.h"
#include "Material/LoaderMaterialIW3.h"
#include "ObjLoading.h" #include "ObjLoading.h"
#include "RawFile/AssetLoaderRawFileIW3.h" #include "RawFile/AssetLoaderRawFileIW3.h"
#include "StringTable/AssetLoaderStringTableIW3.h" #include "StringTable/AssetLoaderStringTableIW3.h"
@@ -90,7 +91,7 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysPreset>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderPhysPreset>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModel>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderXModel>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMaterial>(memory)); collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
collection.AddAssetCreator(CreateImageLoader(memory, searchPath)); collection.AddAssetCreator(CreateImageLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSound>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderSound>(memory));

View File

@@ -0,0 +1,54 @@
#include "LoaderMaterialT5.h"
#include "Game/T5/Material/JsonMaterialLoaderT5.h"
#include "Game/T5/T5.h"
#include "Material/MaterialCommon.h"
#include <format>
#include <iostream>
using namespace T5;
namespace
{
class MaterialLoader final : public AssetCreator<AssetMaterial>
{
public:
MaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(material::GetFileNameForAssetName(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* material = m_memory.Alloc<Material>();
material->info.name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetMaterial> registration(assetName, material);
if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration))
{
std::cerr << std::format("Failed to load material \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace T5
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MaterialLoader>(memory, searchPath);
}
} // namespace T5

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T5/T5.h"
#include "Gdt/IGdtQueryable.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
namespace T5
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace T5

View File

@@ -5,6 +5,7 @@
#include "Game/T5/T5.h" #include "Game/T5/T5.h"
#include "Game/T5/XModel/LoaderXModelT5.h" #include "Game/T5/XModel/LoaderXModelT5.h"
#include "Localize/LoaderLocalizeT5.h" #include "Localize/LoaderLocalizeT5.h"
#include "Material/LoaderMaterialT5.h"
#include "ObjLoading.h" #include "ObjLoading.h"
#include "RawFile/LoaderRawFileT5.h" #include "RawFile/LoaderRawFileT5.h"
#include "StringTable/LoaderStringTableT5.h" #include "StringTable/LoaderStringTableT5.h"
@@ -104,7 +105,7 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderDestructibleDef>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderDestructibleDef>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone)); collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMaterial>(memory)); collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImage>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderImage>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundBank>(memory)); // collection.AddAssetCreator(std::make_unique<AssetLoaderSoundBank>(memory));

View File

@@ -1,8 +1,12 @@
#options GAME (IW4, IW5, T6) #options GAME (IW3, IW4, IW5, T5, T6)
#filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".cpp" #filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".cpp"
#if GAME == "IW4" #if GAME == "IW3"
#define FEATURE_IW3
#define HAS_WATER
#define GAME_LOWER "iw3"
#elif GAME == "IW4"
#define FEATURE_IW4 #define FEATURE_IW4
#define HAS_WATER #define HAS_WATER
#define GAME_LOWER "iw4" #define GAME_LOWER "iw4"
@@ -10,6 +14,10 @@
#define FEATURE_IW5 #define FEATURE_IW5
#define HAS_WATER #define HAS_WATER
#define GAME_LOWER "iw5" #define GAME_LOWER "iw5"
#elif GAME == "T5"
#define FEATURE_T5
#define HAS_WATER
#define GAME_LOWER "t5"
#elif GAME == "T6" #elif GAME == "T6"
#define FEATURE_T6 #define FEATURE_T6
#define GAME_LOWER "t6" #define GAME_LOWER "t6"
@@ -25,6 +33,7 @@
#ifdef HAS_WATER #ifdef HAS_WATER
#include "Base64.h" #include "Base64.h"
#endif #endif
#set COMMON_HEADER "\"Game/" + GAME + "/Common" + GAME + ".h\"" #set COMMON_HEADER "\"Game/" + GAME + "/Common" + GAME + ".h\""
#include COMMON_HEADER #include COMMON_HEADER
#set JSON_HEADER "\"Game/" + GAME + "/Material/JsonMaterial" + GAME + ".h\"" #set JSON_HEADER "\"Game/" + GAME + "/Material/JsonMaterial" + GAME + ".h\""
@@ -94,9 +103,9 @@ namespace
std::cerr << std::format("Cannot load material \"{}\": {}\n", material.info.name, message); std::cerr << std::format("Cannot load material \"{}\": {}\n", material.info.name, message);
} }
#if defined(FEATURE_IW4) || defined(FEATURE_IW5) #if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5)
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned char& gameFlags) static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned char& gameFlags)
#elif defined(FEATURE_T6) #elif defined(FEATURE_T5) || defined(FEATURE_T6)
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags) static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags)
#endif #endif
{ {
@@ -197,7 +206,7 @@ namespace
CreateSamplerStateFromJson(jTexture.samplerState, textureDef.samplerState); CreateSamplerStateFromJson(jTexture.samplerState, textureDef.samplerState);
textureDef.semantic = jTexture.semantic; textureDef.semantic = jTexture.semantic;
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
textureDef.isMatureContent = jTexture.isMatureContent; textureDef.isMatureContent = jTexture.isMatureContent;
#endif #endif
@@ -304,12 +313,18 @@ namespace
structured.alphaTestDisabled = 0; structured.alphaTestDisabled = 0;
structured.alphaTest = GFXS_ALPHA_TEST_GT_0; structured.alphaTest = GFXS_ALPHA_TEST_GT_0;
} }
#if defined(FEATURE_IW4) || defined(FEATURE_IW5) #if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5)
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::LT128) else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::LT128)
{ {
structured.alphaTestDisabled = 0; structured.alphaTestDisabled = 0;
structured.alphaTest = GFXS_ALPHA_TEST_LT_128; structured.alphaTest = GFXS_ALPHA_TEST_LT_128;
} }
#elif defined(FEATURE_T5)
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GE255)
{
structured.alphaTestDisabled = 0;
structured.alphaTest = GFXS_ALPHA_TEST_GE_255;
}
#endif #endif
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GE128) else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GE128)
{ {
@@ -403,9 +418,10 @@ namespace
} }
material.info.surfaceTypeBits = jMaterial.surfaceTypeBits; material.info.surfaceTypeBits = jMaterial.surfaceTypeBits;
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
material.info.layeredSurfaceTypes = jMaterial.layeredSurfaceTypes; material.info.layeredSurfaceTypes = jMaterial.layeredSurfaceTypes;
material.info.hashIndex = static_cast<uint16_t>(jMaterial.hashIndex); #endif
#if defined(FEATURE_T6)
material.info.surfaceFlags = jMaterial.surfaceFlags; material.info.surfaceFlags = jMaterial.surfaceFlags;
material.info.contents = jMaterial.contents; material.info.contents = jMaterial.contents;
#endif #endif
@@ -420,9 +436,6 @@ namespace
material.stateFlags = static_cast<unsigned char>(jMaterial.stateFlags); material.stateFlags = static_cast<unsigned char>(jMaterial.stateFlags);
material.cameraRegion = jMaterial.cameraRegion; material.cameraRegion = jMaterial.cameraRegion;
#ifdef FEATURE_T6
material.probeMipBits = jMaterial.probeMipBits;
#endif
auto* techniqueSet = m_context.LoadDependency<AssetTechniqueSet>(jMaterial.techniqueSet); auto* techniqueSet = m_context.LoadDependency<AssetTechniqueSet>(jMaterial.techniqueSet);
if (!techniqueSet) if (!techniqueSet)

View File

@@ -1,4 +1,4 @@
#options GAME (IW4, IW5, T6) #options GAME (IW3, IW4, IW5, T5, T6)
#filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".h" #filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".h"

View File

@@ -1,467 +0,0 @@
#include "AssetDumperMaterial.h"
#include "Game/IW3/MaterialConstantsIW3.h"
#include "Game/IW3/TechsetConstantsIW3.h"
#include <iomanip>
#include <nlohmann/json.hpp>
#include <sstream>
// #define FLAGS_DEBUG 1
using namespace IW3;
using json = nlohmann::json;
namespace IW3
{
const char* AssetName(const char* name)
{
if (name && name[0] == ',')
return &name[1];
return name;
}
template<size_t S> json ArrayEntry(const char* (&a)[S], const size_t index)
{
assert(index < S);
if (index < S)
return a[index];
return json{};
}
json BuildComplexTableJson(const complex_s* complexTable, const size_t count)
{
auto jArray = json::array();
if (complexTable)
{
for (auto index = 0u; index < count; index++)
{
const auto& entry = complexTable[index];
jArray.emplace_back(json{
{"real", entry.real},
{"imag", entry.imag},
});
}
}
return jArray;
}
json BuildWaterJson(water_t* water)
{
if (!water)
return json{};
return json{
{"floatTime", water->writable.floatTime},
{"H0", BuildComplexTableJson(water->H0, water->M * water->N)},
{"wTerm", water->wTerm ? json{std::vector(water->wTerm, water->wTerm + (water->M * water->N))} : json::array()},
{"M", water->M},
{"N", water->N},
{"Lx", water->Lx},
{"Lz", water->Lz},
{"windvel", water->windvel},
{"winddir", std::vector(std::begin(water->winddir), std::end(water->winddir))},
{"amplitude", water->amplitude},
{"codeConstant", std::vector(std::begin(water->codeConstant), std::end(water->codeConstant))},
{"image", water->image && water->image->name ? AssetName(water->image->name) : nullptr},
};
}
json BuildSamplerStateJson(unsigned char samplerState)
{
static const char* samplerFilterNames[]{
"none",
"nearest",
"linear",
"aniso2x",
"aniso4x",
};
static const char* samplerMipmapNames[]{
"disabled",
"nearest",
"linear",
};
return json{
{"filter", ArrayEntry(samplerFilterNames, (samplerState & SAMPLER_FILTER_MASK) >> SAMPLER_FILTER_SHIFT)},
{"mipmap", ArrayEntry(samplerMipmapNames, (samplerState & SAMPLER_MIPMAP_MASK) >> SAMPLER_MIPMAP_SHIFT)},
{"clampU", (samplerState & SAMPLER_CLAMP_U) ? true : false},
{"clampV", (samplerState & SAMPLER_CLAMP_V) ? true : false},
{"clampW", (samplerState & SAMPLER_CLAMP_W) ? true : false},
};
}
json BuildTextureTableJson(const MaterialTextureDef* textureTable, const size_t count)
{
static const char* semanticNames[]{
"2d",
"function",
"colorMap",
"unused1",
"unused2",
"normalMap",
"unused3",
"unused4",
"specularMap",
"unused5",
"unused6",
"waterMap",
};
auto jArray = json::array();
if (textureTable)
{
for (auto index = 0u; index < count; index++)
{
const auto& entry = textureTable[index];
json jEntry = {
{"samplerState", BuildSamplerStateJson(entry.samplerState)},
{"semantic", ArrayEntry(semanticNames, entry.semantic)},
};
const auto knownMaterialSourceName = knownMaterialSourceNames.find(entry.nameHash);
if (knownMaterialSourceName != knownMaterialSourceNames.end())
{
jEntry["name"] = knownMaterialSourceName->second;
}
else
{
jEntry.merge_patch({
{"nameHash", entry.nameHash },
{"nameStart", entry.nameStart},
{"nameEnd", entry.nameEnd },
});
}
if (entry.semantic == TS_WATER_MAP)
{
jEntry["water"] = BuildWaterJson(entry.u.water);
}
else
{
jEntry["image"] = entry.u.image && entry.u.image->name ? AssetName(entry.u.image->name) : nullptr;
}
jArray.emplace_back(std::move(jEntry));
}
}
return jArray;
}
json BuildConstantTableJson(const MaterialConstantDef* constantTable, const size_t count)
{
auto jArray = json::array();
if (constantTable)
{
for (auto index = 0u; index < count; index++)
{
const auto& entry = constantTable[index];
json jEntry = {
{"literal", std::vector(std::begin(entry.literal), std::end(entry.literal))},
};
const auto nameLen = strnlen(entry.name, std::extent_v<decltype(MaterialConstantDef::name)>);
if (nameLen == std::extent_v<decltype(MaterialConstantDef::name)>)
{
std::string fullLengthName(entry.name, std::extent_v<decltype(MaterialConstantDef::name)>);
const auto fullLengthHash = Common::R_HashString(fullLengthName.c_str(), 0);
if (fullLengthHash == entry.nameHash)
{
jEntry["name"] = fullLengthName;
}
else
{
const auto knownMaterialSourceName = knownMaterialSourceNames.find(entry.nameHash);
if (knownMaterialSourceName != knownMaterialSourceNames.end())
{
jEntry["name"] = knownMaterialSourceName->second;
}
else
{
jEntry.merge_patch({
{"nameHash", entry.nameHash},
{"namePart", fullLengthName},
});
}
}
}
else
{
jEntry["name"] = std::string(entry.name, nameLen);
}
jArray.emplace_back(std::move(jEntry));
}
}
return jArray;
}
json BuildStateBitsTableJson(const GfxStateBits* stateBitsTable, const size_t count)
{
static const char* blendNames[]{
"disabled",
"zero",
"one",
"srcColor",
"invSrcColor",
"srcAlpha",
"invSrcAlpha",
"destAlpha",
"invDestAlpha",
"destColor",
"invDestColor",
};
static const char* blendOpNames[]{
"disabled",
"add",
"subtract",
"revSubtract",
"min",
"max",
};
static const char* depthTestNames[]{
"always",
"less",
"equal",
"lessEqual",
};
static const char* polygonOffsetNames[]{
"0",
"1",
"2",
"shadowMap",
};
static const char* stencilOpNames[]{
"keep",
"zero",
"replace",
"incrSat",
"decrSat",
"invert",
"incr",
"decr",
};
auto jArray = json::array();
if (stateBitsTable)
{
for (auto index = 0u; index < count; index++)
{
const auto& entry = stateBitsTable[index];
const auto srcBlendRgb = (entry.loadBits[0] & GFXS0_SRCBLEND_RGB_MASK) >> GFXS0_SRCBLEND_RGB_SHIFT;
const auto dstBlendRgb = (entry.loadBits[0] & GFXS0_DSTBLEND_RGB_MASK) >> GFXS0_DSTBLEND_RGB_SHIFT;
const auto blendOpRgb = (entry.loadBits[0] & GFXS0_BLENDOP_RGB_MASK) >> GFXS0_BLENDOP_RGB_SHIFT;
const auto srcBlendAlpha = (entry.loadBits[0] & GFXS0_SRCBLEND_ALPHA_MASK) >> GFXS0_SRCBLEND_ALPHA_SHIFT;
const auto dstBlendAlpha = (entry.loadBits[0] & GFXS0_DSTBLEND_ALPHA_MASK) >> GFXS0_DSTBLEND_ALPHA_SHIFT;
const auto blendOpAlpha = (entry.loadBits[0] & GFXS0_BLENDOP_ALPHA_MASK) >> GFXS0_BLENDOP_ALPHA_SHIFT;
const auto depthTest = (entry.loadBits[1] & GFXS1_DEPTHTEST_MASK) >> GFXS1_DEPTHTEST_SHIFT;
const auto polygonOffset = (entry.loadBits[1] & GFXS1_POLYGON_OFFSET_MASK) >> GFXS1_POLYGON_OFFSET_SHIFT;
const auto* alphaTest = "disable";
if (entry.loadBits[0] & GFXS0_ATEST_GT_0)
alphaTest = "gt0";
else if (entry.loadBits[0] & GFXS0_ATEST_LT_128)
alphaTest = "lt128";
else if (entry.loadBits[0] & GFXS0_ATEST_GE_128)
alphaTest = "ge128";
else
assert(entry.loadBits[0] & GFXS0_ATEST_DISABLE);
const auto* cullFace = "none";
if ((entry.loadBits[0] & GFXS0_CULL_MASK) == GFXS0_CULL_BACK)
cullFace = "back";
else if ((entry.loadBits[0] & GFXS0_CULL_MASK) == GFXS0_CULL_FRONT)
cullFace = "front";
else
assert((entry.loadBits[0] & GFXS0_CULL_MASK) == GFXS0_CULL_NONE);
jArray.emplace_back(json{
{"srcBlendRgb", ArrayEntry(blendNames, srcBlendRgb)},
{"dstBlendRgb", ArrayEntry(blendNames, dstBlendRgb)},
{"blendOpRgb", ArrayEntry(blendOpNames, blendOpRgb)},
{"alphaTest", alphaTest},
{"cullFace", cullFace},
{"srcBlendAlpha", ArrayEntry(blendNames, srcBlendAlpha)},
{"dstBlendAlpha", ArrayEntry(blendNames, dstBlendAlpha)},
{"blendOpAlpha", ArrayEntry(blendOpNames, blendOpAlpha)},
{"colorWriteRgb", (entry.loadBits[0] & GFXS0_COLORWRITE_RGB) ? true : false},
{"colorWriteAlpha", (entry.loadBits[0] & GFXS0_COLORWRITE_ALPHA) ? true : false},
{"polymodeLine", (entry.loadBits[0] & GFXS0_POLYMODE_LINE) ? true : false},
{"depthWrite", (entry.loadBits[1] & GFXS1_DEPTHWRITE) ? true : false},
{"depthTest", (entry.loadBits[1] & GFXS1_DEPTHTEST_DISABLE) ? json("disable") : ArrayEntry(depthTestNames, depthTest)},
{"polygonOffset", ArrayEntry(polygonOffsetNames, polygonOffset)},
{"stencilFrontEnabled", (entry.loadBits[1] & GFXS1_STENCIL_FRONT_ENABLE) ? true : false},
{"stencilBackEnabled", (entry.loadBits[1] & GFXS1_STENCIL_BACK_ENABLE) ? true : false},
{"stencilFrontPass", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_FRONT_PASS_SHIFT) & GFXS_STENCILOP_MASK)},
{"stencilFrontFail", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_FRONT_FAIL_SHIFT) & GFXS_STENCILOP_MASK)},
{"stencilFrontZFail", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_FRONT_ZFAIL_SHIFT) & GFXS_STENCILOP_MASK)},
{"stencilFrontFunc", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_FRONT_FUNC_SHIFT) & GFXS_STENCILOP_MASK)},
{"stencilBackPass", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_BACK_PASS_SHIFT) & GFXS_STENCILOP_MASK)},
{"stencilBackFail", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_BACK_FAIL_SHIFT) & GFXS_STENCILOP_MASK)},
{"stencilBackZFail", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_BACK_ZFAIL_SHIFT) & GFXS_STENCILOP_MASK)},
{"stencilBackFunc", ArrayEntry(stencilOpNames, (entry.loadBits[1] >> GFXS1_STENCIL_BACK_FUNC_SHIFT) & GFXS_STENCILOP_MASK)},
});
}
}
return jArray;
}
json BuildSurfaceTypeBitsJson(const unsigned surfaceTypeBits)
{
if (!surfaceTypeBits)
return json(surfaceTypeNames[SURF_TYPE_DEFAULT]);
static constexpr auto NON_SURFACE_TYPE_BITS =
~(std::numeric_limits<unsigned>::max() >> ((sizeof(unsigned) * 8) - (static_cast<unsigned>(SURF_TYPE_NUM) - 1)));
assert((surfaceTypeBits & NON_SURFACE_TYPE_BITS) == 0);
std::ostringstream ss;
auto firstSurfaceType = true;
for (auto surfaceTypeIndex = static_cast<unsigned>(SURF_TYPE_BARK); surfaceTypeIndex < SURF_TYPE_NUM; surfaceTypeIndex++)
{
if ((surfaceTypeBits & (1 << (surfaceTypeIndex - 1))) == 0)
continue;
if (firstSurfaceType)
firstSurfaceType = false;
else
ss << ",";
ss << surfaceTypeNames[surfaceTypeIndex];
}
if (firstSurfaceType)
return json(surfaceTypeNames[SURF_TYPE_DEFAULT]);
return json(ss.str());
}
json BuildCharFlagsJson(const std::string& prefix, const unsigned char gameFlags)
{
std::vector<std::string> values;
for (auto i = 0u; i < (sizeof(gameFlags) * 8u); i++)
{
if (gameFlags & (1 << i))
{
std::ostringstream ss;
ss << prefix << " 0x" << std::hex << (1 << i);
values.emplace_back(ss.str());
}
}
return json(values);
}
} // namespace IW3
bool AssetDumperMaterial::ShouldDump(XAssetInfo<Material>* asset)
{
return true;
}
void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset)
{
auto* material = asset->Asset();
std::ostringstream ss;
ss << "materials/" << asset->m_name << ".json";
const auto assetFile = context.OpenAssetFile(ss.str());
if (!assetFile)
return;
auto& stream = *assetFile;
static const char* cameraRegionNames[]{"lit", "decal", "emissive", "none"};
static std::unordered_map<size_t, std::string> sortKeyNames{
{0, "distortion" },
{1, "opaque water" },
{2, "boat hull" },
{3, "opaque ambient" },
{4, "opaque" },
{5, "sky" },
{6, "skybox - sun / moon" },
{7, "skybox - clouds" },
{8, "skybox - horizon" },
{9, "decal - bottom 1" },
{10, "decal - bottom 2" },
{11, "decal - bottom 3" },
{12, "decal - static decal" },
{13, "decal - middle 1" },
{14, "decal - middle 2" },
{15, "decal - middle 3" },
{24, "decal - weapon impact" },
{29, "decal - top 1" },
{30, "decal - top 2" },
{31, "decal - top 3" },
{32, "multiplicative" },
{33, "banner / curtain" },
{34, "hair" },
{35, "underwater" },
{36, "transparent water" },
{37, "corona" },
{38, "window inside" },
{39, "window outside" },
{40, "before effects - bottom"},
{41, "before effects - middle"},
{42, "before effects - top" },
{43, "blend / additive" },
{48, "effect - auto sort" },
{56, "after effects - bottom" },
{57, "after effects - middle" },
{58, "after effects - top" },
{59, "viewmodel effect" },
};
const auto foundSortKeyName = sortKeyNames.find(material->info.sortKey);
assert(foundSortKeyName != sortKeyNames.end());
const json j = {
{"info",
{
#if defined(FLAGS_DEBUG) && FLAGS_DEBUG == 1
{"gameFlags", BuildCharFlagsJson("gameFlag", material->info.gameFlags)}, // TODO: Find out what gameflags mean
#else
{"gameFlags", material->info.gameFlags}, // TODO: Find out what gameflags mean
#endif
{"sortKey", foundSortKeyName != sortKeyNames.end() ? foundSortKeyName->second : std::to_string(material->info.sortKey)},
{"textureAtlasRowCount", material->info.textureAtlasRowCount},
{"textureAtlasColumnCount", material->info.textureAtlasColumnCount},
{"drawSurf",
{{"objectId", static_cast<unsigned>(material->info.drawSurf.fields.objectId)},
{"reflectionProbeIndex", static_cast<unsigned>(material->info.drawSurf.fields.reflectionProbeIndex)},
{"customIndex", static_cast<unsigned>(material->info.drawSurf.fields.customIndex)},
{"materialSortedIndex", static_cast<unsigned>(material->info.drawSurf.fields.materialSortedIndex)},
{"prepass", static_cast<unsigned>(material->info.drawSurf.fields.prepass)},
{"useHeroLighting", static_cast<unsigned>(material->info.drawSurf.fields.primaryLightIndex)},
{"surfType", static_cast<unsigned>(material->info.drawSurf.fields.surfType)},
{"primarySortKey", static_cast<unsigned>(material->info.drawSurf.fields.primarySortKey)}}},
{"surfaceTypeBits", BuildSurfaceTypeBitsJson(material->info.surfaceTypeBits)},
{"hashIndex", material->info.hashIndex}}},
{"stateBitsEntry", std::vector(std::begin(material->stateBitsEntry), std::end(material->stateBitsEntry))},
#if defined(FLAGS_DEBUG) && FLAGS_DEBUG == 1
{"stateFlags", BuildCharFlagsJson("stateFlag", material->stateFlags)},
#else
{"stateFlags", material->stateFlags},
#endif
{"cameraRegion", ArrayEntry(cameraRegionNames, material->cameraRegion)},
{"techniqueSet", material->techniqueSet && material->techniqueSet->name ? AssetName(material->techniqueSet->name) : nullptr},
{"textureTable", BuildTextureTableJson(material->textureTable, material->textureCount)},
{"constantTable", BuildConstantTableJson(material->constantTable, material->constantCount)},
{"stateBitsTable", BuildStateBitsTableJson(material->stateBitsTable, material->stateBitsCount)},
};
stream << std::setw(4) << j;
}

View File

@@ -0,0 +1,30 @@
#include "DumperMaterialIW3.h"
#include "Game/IW3/Material/JsonMaterialWriterIW3.h"
#include "Game/IW3/Material/MaterialConstantZoneStateIW3.h"
#include "Material/MaterialCommon.h"
using namespace IW3;
void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool)
{
auto* materialConstantState = context.GetZoneAssetDumperState<MaterialConstantZoneState>();
materialConstantState->ExtractNamesFromZone();
AbstractAssetDumper::DumpPool(context, pool);
}
bool AssetDumperMaterial::ShouldDump(XAssetInfo<Material>* asset)
{
return true;
}
void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset)
{
const auto assetFile = context.OpenAssetFile(material::GetFileNameForAssetName(asset->m_name));
if (!assetFile)
return;
DumpMaterialAsJson(*assetFile, *asset->Asset(), context);
}

View File

@@ -7,6 +7,9 @@ namespace IW3
{ {
class AssetDumperMaterial final : public AbstractAssetDumper<Material> class AssetDumperMaterial final : public AbstractAssetDumper<Material>
{ {
public:
void DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool) override;
protected: protected:
bool ShouldDump(XAssetInfo<Material>* asset) override; bool ShouldDump(XAssetInfo<Material>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset) override; void DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset) override;

View File

@@ -0,0 +1,250 @@
#include "MaterialConstantZoneStateIW3.h"
#include "Game/IW3/CommonIW3.h"
#include "Game/IW3/GameAssetPoolIW3.h"
#include "Game/IW3/GameIW3.h"
#include "ObjWriting.h"
namespace IW3
{
const char* KNOWN_CONSTANT_NAMES[]{
"worldViewProjectionMatrix",
"worldViewMatrix2",
"worldViewMatrix1",
"worldViewMatrix",
"worldOutdoorLookupMatrix",
"worldMatrix",
"waterColor",
"viewportDimensions",
"viewProjectionMatrix",
"uvScale",
"uvAnimParms",
"thermalColorOffset",
"sunShadowmapPixelAdjust",
"ssaoParms",
"spotShadowmapPixelAdjust",
"shadowmapSwitchPartition",
"shadowmapScale",
"shadowmapPolygonOffset",
"shadowLookupMatrix",
"renderTargetSize",
"renderSourceSize",
"projectionMatrix",
"playlistPopulationParams",
"pixelCostFracs",
"pixelCostDecode",
"particleCloudSparkColor2",
"particleCloudSparkColor1",
"particleCloudSparkColor0",
"particleCloudMatrix2",
"particleCloudMatrix1",
"particleCloudMatrix",
"particleCloudColor",
"outdoorFeatherParms",
"oceanUVAnimParmPaintedFoam",
"oceanUVAnimParmOctave2",
"oceanUVAnimParmOctave1",
"oceanUVAnimParmOctave0",
"oceanUVAnimParmFoam",
"oceanUVAnimParmDetail1",
"oceanUVAnimParmDetail0",
"oceanScrollParms",
"oceanMiscParms",
"oceanFoamParms",
"oceanAmplitude",
"materialColor",
"lightprobeAmbient",
"lightingLookupScale",
"lightSpotFactors",
"lightSpotDir",
"lightSpecular",
"lightPosition",
"lightFalloffPlacement",
"lightDiffuse",
"inverseWorldViewMatrix",
"inverseViewProjectionMatrix",
"inverseTransposeWorldViewMatrix",
"heatMapDetail",
"glowSetup",
"glowApply",
"gameTime",
"fullscreenDistortion",
"fogSunDir",
"fogSunConsts",
"fogSunColorLinear",
"fogSunColorGamma",
"fogConsts",
"fogColorLinear",
"fogColorGamma",
"flagParms",
"filterTap",
"featherParms",
"falloffParms",
"falloffEndColor",
"falloffBeginColor",
"fadeEffect",
"eyeOffsetParms",
"eyeOffset",
"envMapParms",
"dustTint",
"dustParms",
"dustEyeParms",
"dofRowDelta",
"dofLerpScale",
"dofLerpBias",
"dofEquationViewModelAndFarBlur",
"dofEquationScene",
"distortionScale",
"detailScale",
"depthFromClip",
"debugBumpmap",
"colorTintQuadraticDelta",
"colorTintDelta",
"colorTintBase",
"colorSaturationR",
"colorSaturationG",
"colorSaturationB",
"colorObjMin",
"colorObjMax",
"colorMatrixR",
"colorMatrixG",
"colorMatrixB",
"colorBias",
"codeMeshArg",
"clipSpaceLookupScale",
"clipSpaceLookupOffset",
"baseLightingCoords",
};
const char* KNOWN_TEXTURE_DEF_NAMES[]{
"attenuation",
"attenuationSampler",
"cinematicA",
"cinematicASampler",
"cinematicCb",
"cinematicCbSampler",
"cinematicCr",
"cinematicCrSampler",
"cinematicY",
"cinematicYSampler",
"colorMap",
"colorMap1",
"colorMap2",
"colorMapPostSun",
"colorMapPostSunSampler",
"colorMapSampler",
"colorMapSampler1",
"colorMapSampler2",
"cucoloris",
"cucolorisSampler",
"detailMap",
"detailMapSampler",
"dust",
"dustSampler",
"fadeMap",
"fadeMapSampler",
"floatZ",
"floatZSampler",
"grainMap",
"grainMapSampler",
"halfParticleColor",
"halfParticleColorSampler",
"halfParticleDepth",
"halfParticleDepthSampler",
"heatmap",
"heatmapSampler",
"lightmapPrimary",
"lightmapSamplerPrimary",
"lightmapSamplerSecondary",
"lightmapSecondary",
"lookupMap",
"lookupMapSampler",
"modelLighting",
"modelLightingSampler",
"normalMap",
"normalMapSampler",
"oceanColorRamp",
"oceanColorRampSampler",
"oceanDetailNormal",
"oceanDetailNormalSampler",
"oceanDisplacement",
"oceanDisplacementSampler",
"oceanEnv",
"oceanEnvSampler",
"oceanFoam",
"oceanFoamSampler",
"oceanHeightNormal",
"oceanHeightNormalSampler",
"oceanPaintedFoam",
"oceanPaintedFoamSampler",
"outdoorMap",
"outdoorMapSampler",
"population",
"populationSampler",
"reflectionProbe",
"reflectionProbeSampler",
"shadowmapSamplerSpot",
"shadowmapSamplerSun",
"shadowmapSpot",
"shadowmapSun",
"skyMap",
"skyMapSampler",
"specularMap",
"specularMapSampler",
"ssao",
"ssaoSampler",
"worldMap",
"worldMapSampler",
};
void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{
for (const auto* zone : IGame::GetGameById(GameId::IW3)->GetZones())
{
const auto* assetPools = dynamic_cast<const GameAssetPoolIW3*>(zone->m_pools.get());
if (!assetPools)
return;
for (const auto* techniqueSetInfo : *assetPools->m_technique_set)
{
const auto* techniqueSet = techniqueSetInfo->Asset();
for (const auto* technique : techniqueSet->techniques)
{
if (technique)
ExtractNamesFromTechnique(technique);
}
}
}
}
unsigned MaterialConstantZoneState::HashString(const std::string& str)
{
return Common::R_HashString(str.c_str());
}
void MaterialConstantZoneState::ExtractNamesFromTechnique(const MaterialTechnique* technique)
{
if (!ShouldDumpFromStruct(technique))
return;
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
{
const auto& pass = technique->passArray[passIndex];
if (pass.vertexShader && pass.vertexShader->prog.loadDef.program)
ExtractNamesFromShader(pass.vertexShader->prog.loadDef.program, pass.vertexShader->prog.loadDef.programSize);
if (pass.pixelShader && pass.pixelShader->prog.loadDef.program)
ExtractNamesFromShader(pass.pixelShader->prog.loadDef.program, pass.pixelShader->prog.loadDef.programSize);
}
}
void MaterialConstantZoneState::AddStaticKnownNames()
{
for (const auto* knownConstantName : KNOWN_CONSTANT_NAMES)
AddConstantName(knownConstantName);
for (const auto* knownTextureDefName : KNOWN_TEXTURE_DEF_NAMES)
AddTextureDefName(knownTextureDefName);
}
} // namespace IW3

View File

@@ -0,0 +1,18 @@
#pragma once
#include "Game/IW3/IW3.h"
#include "Material/AbstractMaterialConstantZoneState.h"
#include <string>
namespace IW3
{
class MaterialConstantZoneState final : public AbstractMaterialConstantZoneStateDx9
{
protected:
void ExtractNamesFromZoneInternal() override;
void ExtractNamesFromTechnique(const MaterialTechnique* technique);
void AddStaticKnownNames() override;
unsigned HashString(const std::string& str) override;
};
} // namespace IW3

View File

@@ -4,12 +4,12 @@
#include "AssetDumpers/AssetDumperLoadedSound.h" #include "AssetDumpers/AssetDumperLoadedSound.h"
#include "AssetDumpers/AssetDumperLocalizeEntry.h" #include "AssetDumpers/AssetDumperLocalizeEntry.h"
#include "AssetDumpers/AssetDumperMapEnts.h" #include "AssetDumpers/AssetDumperMapEnts.h"
#include "AssetDumpers/AssetDumperMaterial.h"
#include "AssetDumpers/AssetDumperRawFile.h" #include "AssetDumpers/AssetDumperRawFile.h"
#include "AssetDumpers/AssetDumperStringTable.h" #include "AssetDumpers/AssetDumperStringTable.h"
#include "AssetDumpers/AssetDumperWeapon.h" #include "AssetDumpers/AssetDumperWeapon.h"
#include "AssetDumpers/AssetDumperXModel.h" #include "AssetDumpers/AssetDumperXModel.h"
#include "Game/IW3/GameAssetPoolIW3.h" #include "Game/IW3/GameAssetPoolIW3.h"
#include "Material/DumperMaterialIW3.h"
#include "ObjWriting.h" #include "ObjWriting.h"
using namespace IW3; using namespace IW3;

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "IObjWriter.h" #include "IObjWriter.h"
namespace IW3 namespace IW3

View File

@@ -199,20 +199,20 @@ namespace IW4
void MaterialConstantZoneState::ExtractNamesFromZoneInternal() void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{ {
for (const auto* zone : IGame::GetGameById(GameId::IW5)->GetZones()) for (const auto* zone : IGame::GetGameById(GameId::IW4)->GetZones())
{ {
const auto* iw5AssetPools = dynamic_cast<const GameAssetPoolIW4*>(zone->m_pools.get()); const auto* assetPools = dynamic_cast<const GameAssetPoolIW4*>(zone->m_pools.get());
if (!iw5AssetPools) if (!assetPools)
return; return;
for (const auto* vertexShaderAsset : *iw5AssetPools->m_material_vertex_shader) for (const auto* vertexShaderAsset : *assetPools->m_material_vertex_shader)
{ {
const auto* vertexShader = vertexShaderAsset->Asset(); const auto* vertexShader = vertexShaderAsset->Asset();
if (ShouldDumpFromStruct(vertexShader)) if (ShouldDumpFromStruct(vertexShader))
ExtractNamesFromShader(vertexShader->prog.loadDef.program, static_cast<size_t>(vertexShader->prog.loadDef.programSize) * sizeof(uint32_t)); ExtractNamesFromShader(vertexShader->prog.loadDef.program, static_cast<size_t>(vertexShader->prog.loadDef.programSize) * sizeof(uint32_t));
} }
for (const auto* pixelShaderAsset : *iw5AssetPools->m_material_pixel_shader) for (const auto* pixelShaderAsset : *assetPools->m_material_pixel_shader)
{ {
const auto* pixelShader = pixelShaderAsset->Asset(); const auto* pixelShader = pixelShaderAsset->Asset();
if (ShouldDumpFromStruct(pixelShader)) if (ShouldDumpFromStruct(pixelShader))

View File

@@ -26,5 +26,6 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Mat
if (!assetFile) if (!assetFile)
return; return;
DumpMaterialAsJson(*assetFile, *asset->Asset(), context); const auto* material = asset->Asset();
DumpMaterialAsJson(*assetFile, *material, context);
} }

View File

@@ -0,0 +1,35 @@
#include "DumperMaterialT5.h"
#include "Game/T5/Material/JsonMaterialWriterT5.h"
#include "Game/T5/Material/MaterialConstantZoneStateT5.h"
#include "Material/MaterialCommon.h"
#include <assert.h>
using namespace T5;
void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool)
{
auto* materialConstantState = context.GetZoneAssetDumperState<MaterialConstantZoneState>();
materialConstantState->ExtractNamesFromZone();
AbstractAssetDumper::DumpPool(context, pool);
}
bool AssetDumperMaterial::ShouldDump(XAssetInfo<Material>* asset)
{
return true;
}
void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset)
{
const auto assetFile = context.OpenAssetFile(material::GetFileNameForAssetName(asset->m_name));
if (!assetFile)
return;
const auto* material = asset->Asset();
assert(material->info.gameFlags < 0x400);
assert(material->maxStreamedMips == 0);
DumpMaterialAsJson(*assetFile, *material, context);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T5/T5.h"
namespace T5
{
class AssetDumperMaterial final : public AbstractAssetDumper<Material>
{
public:
void DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool) override;
protected:
bool ShouldDump(XAssetInfo<Material>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset) override;
};
} // namespace T5

View File

@@ -0,0 +1,524 @@
#include "MaterialConstantZoneStateT5.h"
#include "Game/T5/CommonT5.h"
#include "Game/T5/GameAssetPoolT5.h"
#include "Game/T5/GameT5.h"
#include "ObjWriting.h"
namespace T5
{
const char* KNOWN_CONSTANT_NAMES[]{
"AngularVelocityScale",
"AnimSpeed",
"Background",
"BackgroundColor",
"BackgroundNoise",
"BakedLightingIntensity",
"BloodBrightness",
"BloodIntensity",
"BlurAmount",
"CapWidth",
"Char_Size",
"Char_Width",
"Coarseness",
"Color",
"ColorAmount",
"ColorBias",
"Color_Map_Noise",
"Color_Map_Scale",
"Color_Map_Size_Scale",
"DDXScale",
"DDYScale",
"DarkenAmount",
"DarkenPower",
"Detail_Amount",
"Detail_Normal_Tile",
"Diffuse_Normal_Height_Facing",
"Dimensions",
"DispersionAmount",
"Dolly",
"EdgeColor",
"EdgeHarshness",
"EdgeIntensity",
"EdgeMaxDist",
"EdgeMinDist",
"EdgeSize",
"Edge_Color_Multiplier",
"Emissive_Amount",
"EnemiesColor",
"Exposure",
"FPS",
"Fade_Distance",
"Fill_Direction",
"Fill_Direction2",
"FirstFrame",
"FlareIntensity",
"FlareScale",
"FlattenEdges",
"Flicker_Max",
"Flicker_Min",
"Flicker_Seed",
"Flicker_Speed",
"Font_Color",
"Gamma",
"GlossAmount",
"Gloss_Amount",
"Glow_Alt_Color",
"Glow_Color",
"Glow_Falloff",
"GradientColor",
"GradientMax",
"GradientMin",
"Grain_Amount",
"Grain_Color",
"Grid",
"Hardness",
"Heart_Rate_Offset",
"Heart_Rate_Scale",
"Highlight_1_Brightness",
"Highlight_1_Sharpness",
"Highlight_2_Brightness",
"Highlight_2_Sharpness",
"Highlight_2_Size",
"Hightlight_1_Size",
"Holo_Scale",
"LastFrame",
"Layer1Alpha",
"Layer1Depth",
"Layer1Offset",
"Layer1OffsetBobbleDelay",
"Layer1OffsetBobbleSpeedAndSize",
"Layer1Origin",
"Layer1Rotation",
"Layer1Scale",
"Layer1ScaleBobbleDelay",
"Layer1ScaleBobbleSpeedAndSize",
"Layer1Scroll",
"Layer2Alpha",
"Layer2Depth",
"Layer2Offset",
"Layer2OffsetBobbleDelay",
"Layer2OffsetBobbleSpeedAndSize",
"Layer2Origin",
"Layer2Rotation",
"Layer2Scale",
"Layer2ScaleBobbleDelay",
"Layer2ScaleBobbleSpeedAndSize",
"Layer2Scroll",
"Layer3Alpha",
"Layer3Depth",
"Layer3Offset",
"Layer3Origin",
"Layer3Rotation",
"Layer3Scale",
"Layer3Scroll",
"Layer4Alpha",
"Layer4Depth",
"Layer4Offset",
"Layer4Origin",
"Layer4Rotation",
"Layer4Scale",
"Layer4Scroll",
"LineColor",
"LineNoise",
"LineWidth",
"MaxDepth",
"MaxFlickerColor",
"MaxPulseDepth",
"MaxResolution",
"Max_Color",
"Maximum_Distance",
"Midlayer_Depth",
"MinDepth",
"MinFlickerColor",
"MinResolution",
"MinStatic",
"MinVelocityFraction",
"Min_Color",
"Min_Player_Intensity",
"MomentumColor",
"NegativeColor",
"NoisePower",
"Noise_Scale",
"NormalHeightMultiplier",
"Normal_Detail_Height",
"Normal_Detail_Scale",
"Normal_Map_Size_Scale",
"Normal_Variance_Scale",
"NumFrames",
"Outline_Lookup_Scale",
"OverallAmount",
"OverallBrightness",
"Overlay_Color",
"P1",
"P2",
"Padding",
"Player_Color_Multiplier",
"Player_Lookup_Scale",
"PositiveColor",
"Power",
"PulseColor",
"PulseInterval",
"PulseTime",
"Pulse_Color_Multiplier",
"Pulse_Lookup_Scale",
"Radius",
"ReflectionAmount",
"Reflection_Amount",
"Reflection_Blur",
"Reticle_Alt_Color",
"Reticle_Color",
"Row_Chars_",
"Scale",
"ScanlineColor",
"ScanlineIntensity",
"ScanlineOffset",
"ScanlinePower",
"ScanlineSpeed",
"ScatterAmount",
"ScatterSize",
"SceneNoise",
"SparkleBrightness",
"SparkleDensity",
"SparklePower",
"SparkleProbeAmount",
"SparkleScale",
"SparkleSpecAmount",
"SparkleWash",
"SpecGloss_Map_Size_Scale",
"SpecularAmount",
"SpecularColor",
"Specular_Amount",
"Specular_Decay_Threshold",
"Speed",
"StaticAmount",
"StaticLookupSpeed",
"StaticLookupX",
"StaticScale",
"Static_Size",
"Static_amount",
"TearLookupMaxX",
"TearLookupMinX",
"TearLookupSpeed",
"TearMultiplier",
"TearPower",
"Thickness",
"TickMarkColorAndHarshness",
"Tint",
"VelocityScale",
"VignetteMultiplier",
"VignettePower",
"WarpAmount",
"WarpHeight",
"WarpScale",
"WarpSpeed",
"WashOut",
"WashoutMultiply",
"WaterDirection",
"WaterHeight",
"WaterRefraction",
"WaterScale1",
"WaterScale2",
"WaterSpeed1",
"WaterSpeed2",
"Zoom",
"alphaDissolveParms",
"alphaRevealParms",
"alphaRevealParms1",
"alphaRevealParms2",
"alphaRevealParms3",
"alphaRevealParms4",
"clipSpaceLookupOffset",
"clipSpaceLookupScale",
"cloudsFeather",
"cloudsHeights",
"cloudsUVMad1",
"cloudsUVMad2",
"cloudsUVMul1",
"cloudsUVMul2",
"codeMeshArg",
"colorDetailScale",
"colorObjMax",
"colorObjMaxBaseBlend",
"colorObjMin",
"colorObjMinBaseBlend",
"colorTint",
"debugBumpmap",
"debugPerformance",
"detailScale",
"detailScale1",
"detailScale2",
"detailScale3",
"detailScale4",
"distortionScale",
"dofEquationScene",
"dofEquationViewModelAndFarBlur",
"dofLerpBias",
"dofLerpDownBias",
"dofLerpDownScale",
"dofLerpScale",
"dofLerpUpBias",
"dofLerpUpScale",
"dofRowDelta",
"eyeOffsetParms",
"falloffBeginColor",
"falloffEndColor",
"falloffParms",
"featherParms",
"flagParams",
"framebufferRead",
"gameTime",
"hdrAmount",
"inverseTransposeWorldMatrix",
"inverseTransposeWorldViewMatrix",
"inverseWorldMatrix",
"inverseWorldViewMatrix",
"motionblurDirectionAndMagnitude",
"occlusionAmount",
"occlusionAmount1",
"occlusionAmount2",
"occlusionAmount3",
"occlusionAmount4",
"particleCloudColor",
"particleCloudMatrix",
"particleCloudVelWorld",
"resizeParams1",
"resizeParams2",
"scaleRGB",
"scriptVector0",
"scriptVector1",
"scriptVector2",
"scriptVector3",
"scriptVector4",
"scriptVector5",
"scriptVector6",
"scriptVector7",
"skyBoxCloudWeights",
"skyBoxRotationSize",
"skyColorParms",
"spotLightWeight",
"treeCanopyLightingParms",
"treeCanopyScatterColor",
"treeCanopySwayParms",
"ui3dUVSetup0",
"ui3dUVSetup1",
"ui3dUVSetup2",
"ui3dUVSetup3",
"ui3dUVSetup4",
"ui3dUVSetup5",
"uvAnimParms",
"uvScroll",
"viewMatrix",
"weaponParam0",
"weaponParam1",
"weaponParam2",
"weaponParam3",
"weaponParam4",
"weaponParam5",
"weaponParam6",
"weaponParam7",
"weaponParam8",
"weaponParam9",
"worldViewMatrix",
"worldViewProjectionMatrix",
};
const char* KNOWN_TEXTURE_DEF_NAMES[]{
"AddMap",
"Blip_Mask",
"BlockNoise",
"CS_Z_buffer",
"Camo_Detail_Map",
"Color_Map",
"CompassMap",
"Detail_Map",
"Diffuse",
"Diffuse_Map",
"DpadTexture",
"FontTextutre",
"Grain_Map",
"GridTexture",
"GrimeMap",
"Heart_Rate_Image",
"Hologram_Diffuse",
"Image",
"Layer1Map",
"Layer2Map",
"Layer3Map",
"Layer4Map",
"Lookup",
"Lookup2",
"LookupMap",
"Mask",
"Noise",
"Noise_Texture",
"NormalDetailMap",
"Normal_Detail_Map",
"Normal_Map",
"Overlay_Map",
"Reflection_Mask",
"Reveal_Map",
"Rim_Color_Mask",
"Rim_Specular_Mask",
"Rim_Occlusion_Mask",
"Scanline",
"SparkleMap",
"SpecularAndGloss",
"SpecularAndGloss2",
"Specular_Color_Map",
"Specular_Gloss_Map",
"Specular_Map",
"SpotShadowSamplerState",
"SpotShadowState",
"SpriteMap",
"Static",
"StaticMap",
"Static_Noise_Map",
"SunShadowSamplerState",
"SunShadowState",
"Surface_Normal_Map",
"ThermalMapMask",
"Thermal_Gradient",
"Thermal_Map",
"TickMarkMaterial",
"Tile",
"WarpMap",
"WaterNormalMap",
"Weapon_Normal_Map",
"Weapon_Specular_Map",
"Wireframe",
"ZBuffer_Map",
"attenuation",
"attenuationSampler",
"baseLut2D",
"baseLut2DSampler",
"cinematicA",
"cinematicASampler",
"cinematicCb",
"cinematicCbSampler",
"cinematicCr",
"cinematicCrSampler",
"cinematicY",
"cinematicYSampler",
"codeTexture0",
"codeTexture1",
"codeTexture2",
"color",
"colorDetailMap",
"colorDetailMapSampler",
"colorMap",
"colorMap1",
"colorMap2",
"colorMap2D",
"colorMapPostSun",
"colorMapPostSunSampler",
"colorMapSampler",
"colorMapSampler1",
"colorMapSampler2",
"colorSampler",
"detailMap",
"detailMapSampler",
"dlightAttenuation",
"dlightAttenuationSampler",
"floatZ",
"floatZSampler",
"imageSampler",
"lightmapSamplerSecondary",
"lightmapSecondary",
"lut2D",
"lut2DSampler",
"lut3D",
"lut3DSampler",
"missileCam",
"missileCamSampler",
"modelLighting",
"modelLightingSampler",
"normalMap",
"normalMap1",
"normalMap2",
"normalMapSampler",
"normalMapSampler1",
"normalMapSampler2",
"occlusionMap",
"occlusionMapSampler",
"occMap",
"occMapSampler",
"outdoorMap",
"outdoorMapSampler",
"radiantDiffuseMap",
"rawFloatZ",
"rawFloatZSampler",
"reflectionProbe",
"reflectionProbeSampler",
"shadowmapSamplerSpot",
"shadowmapSamplerSun",
"shadowmapSpot",
"shadowmapSun",
"sonarColor",
"sonarColorSampler",
"sonarDepth",
"sonarDepthSampler",
"source",
"specularMap",
"specularMap1",
"specularMap2",
"specularMapSampler",
"specularMapSampler1",
"specularMapSampler2",
"stencil",
"stencilSampler",
"ui3d",
"ui3dSampler",
};
void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{
for (const auto* zone : IGame::GetGameById(GameId::T6)->GetZones())
{
const auto* assetPools = dynamic_cast<const GameAssetPoolT5*>(zone->m_pools.get());
if (!assetPools)
return;
for (const auto* techniqueSetInfo : *assetPools->m_technique_set)
{
const auto* techniqueSet = techniqueSetInfo->Asset();
for (const auto* technique : techniqueSet->techniques)
{
if (technique)
ExtractNamesFromTechnique(technique);
}
}
}
}
unsigned MaterialConstantZoneState::HashString(const std::string& str)
{
return Common::R_HashString(str.c_str());
}
void MaterialConstantZoneState::ExtractNamesFromTechnique(const MaterialTechnique* technique)
{
if (!ShouldDumpFromStruct(technique))
return;
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
{
const auto& pass = technique->passArray[passIndex];
if (pass.vertexShader && pass.vertexShader->prog.loadDef.program)
ExtractNamesFromShader(pass.vertexShader->prog.loadDef.program, pass.vertexShader->prog.loadDef.programSize);
if (pass.pixelShader && pass.pixelShader->prog.loadDef.program)
ExtractNamesFromShader(pass.pixelShader->prog.loadDef.program, pass.pixelShader->prog.loadDef.programSize);
}
}
void MaterialConstantZoneState::AddStaticKnownNames()
{
for (const auto* knownConstantName : KNOWN_CONSTANT_NAMES)
AddConstantName(knownConstantName);
for (const auto* knownTextureDefName : KNOWN_TEXTURE_DEF_NAMES)
AddTextureDefName(knownTextureDefName);
}
} // namespace T5

View File

@@ -0,0 +1,18 @@
#pragma once
#include "Game/T5/T5.h"
#include "Material/AbstractMaterialConstantZoneState.h"
#include <string>
namespace T5
{
class MaterialConstantZoneState final : public AbstractMaterialConstantZoneStateDx11
{
protected:
void ExtractNamesFromZoneInternal() override;
void ExtractNamesFromTechnique(const MaterialTechnique* technique);
void AddStaticKnownNames() override;
unsigned HashString(const std::string& str) override;
};
} // namespace T5

View File

@@ -10,6 +10,7 @@
#include "AssetDumpers/AssetDumperWeapon.h" #include "AssetDumpers/AssetDumperWeapon.h"
#include "AssetDumpers/AssetDumperXModel.h" #include "AssetDumpers/AssetDumperXModel.h"
#include "Game/T5/GameAssetPoolT5.h" #include "Game/T5/GameAssetPoolT5.h"
#include "Material/DumperMaterialT5.h"
#include "ObjWriting.h" #include "ObjWriting.h"
using namespace T5; using namespace T5;
@@ -30,7 +31,7 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const
// DUMP_ASSET_POOL(AssetDumperDestructibleDef, m_destructible_def, ASSET_TYPE_DESTRUCTIBLEDEF) // DUMP_ASSET_POOL(AssetDumperDestructibleDef, m_destructible_def, ASSET_TYPE_DESTRUCTIBLEDEF)
// DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS) // DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS)
DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL) DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL)
// DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL) DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL)
// DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) // DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET)
DUMP_ASSET_POOL(AssetDumperGfxImage, m_image, ASSET_TYPE_IMAGE) DUMP_ASSET_POOL(AssetDumperGfxImage, m_image, ASSET_TYPE_IMAGE)
// DUMP_ASSET_POOL(AssetDumperSndBank, m_sound_bank, ASSET_TYPE_SOUND) // DUMP_ASSET_POOL(AssetDumperSndBank, m_sound_bank, ASSET_TYPE_SOUND)

View File

@@ -4,6 +4,8 @@
#include "Game/T6/Material/MaterialConstantZoneStateT6.h" #include "Game/T6/Material/MaterialConstantZoneStateT6.h"
#include "Material/MaterialCommon.h" #include "Material/MaterialCommon.h"
#include <cassert>
using namespace T6; using namespace T6;
void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool) void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool)
@@ -26,5 +28,9 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Mat
if (!assetFile) if (!assetFile)
return; return;
DumpMaterialAsJson(*assetFile, *asset->Asset(), context); const auto* material = asset->Asset();
assert(material->info.gameFlags < 0x8000);
assert(material->info.hashIndex == 0);
assert(material->probeMipBits == 0);
DumpMaterialAsJson(*assetFile, *material, context);
} }

View File

@@ -1,8 +1,12 @@
#options GAME (IW4, IW5, T6) #options GAME (IW3, IW4, IW5, T5, T6)
#filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".cpp" #filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".cpp"
#if GAME == "IW4" #if GAME == "IW3"
#define FEATURE_IW3
#define HAS_WATER
#define GAME_LOWER "iw3"
#elif GAME == "IW4"
#define FEATURE_IW4 #define FEATURE_IW4
#define HAS_WATER #define HAS_WATER
#define GAME_LOWER "iw4" #define GAME_LOWER "iw4"
@@ -10,6 +14,10 @@
#define FEATURE_IW5 #define FEATURE_IW5
#define HAS_WATER #define HAS_WATER
#define GAME_LOWER "iw5" #define GAME_LOWER "iw5"
#elif GAME == "T5"
#define FEATURE_T5
#define HAS_WATER
#define GAME_LOWER "t5"
#elif GAME == "T6" #elif GAME == "T6"
#define FEATURE_T6 #define FEATURE_T6
#define GAME_LOWER "t6" #define GAME_LOWER "t6"
@@ -56,6 +64,7 @@ namespace
CreateJsonMaterial(jsonMaterial, material); CreateJsonMaterial(jsonMaterial, material);
json jRoot = jsonMaterial; json jRoot = jsonMaterial;
jRoot["$schema"] = "http://openassettools.dev/schema/material.v1.json";
jRoot["_type"] = "material"; jRoot["_type"] = "material";
jRoot["_version"] = 1; jRoot["_version"] = 1;
jRoot["_game"] = GAME_LOWER; jRoot["_game"] = GAME_LOWER;
@@ -140,7 +149,7 @@ namespace
} }
jTextureDef.semantic = static_cast<TextureSemantic>(textureDef.semantic); jTextureDef.semantic = static_cast<TextureSemantic>(textureDef.semantic);
#if defined(FEATURE_T6) #if defined(FEATURE_T5) || defined(FEATURE_T6)
jTextureDef.isMatureContent = textureDef.isMatureContent; jTextureDef.isMatureContent = textureDef.isMatureContent;
#endif #endif
@@ -192,12 +201,12 @@ namespace
jConstantDef.nameFragment = nameFragment; jConstantDef.nameFragment = nameFragment;
} }
jConstantDef.literal = std::vector({ jConstantDef.literal = {
constantDef.literal.x, constantDef.literal.x,
constantDef.literal.y, constantDef.literal.y,
constantDef.literal.z, constantDef.literal.z,
constantDef.literal.w, constantDef.literal.w,
}); };
} }
static void CreateJsonStencil(JsonStencil& jStencil, const unsigned pass, const unsigned fail, const unsigned zFail, const unsigned func) static void CreateJsonStencil(JsonStencil& jStencil, const unsigned pass, const unsigned fail, const unsigned zFail, const unsigned func)
@@ -218,17 +227,22 @@ namespace
assert(structured.alphaTestDisabled assert(structured.alphaTestDisabled
|| structured.alphaTest == GFXS_ALPHA_TEST_GT_0 || structured.alphaTest == GFXS_ALPHA_TEST_GT_0
#if defined(FEATURE_IW4) || defined(FEATURE_IW5) #if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5)
|| structured.alphaTest == GFXS_ALPHA_TEST_LT_128 || structured.alphaTest == GFXS_ALPHA_TEST_LT_128
#elif defined(FEATURE_T5)
|| structured.alphaTest == GFXS_ALPHA_TEST_GE_255
#endif #endif
|| structured.alphaTest == GFXS_ALPHA_TEST_GE_128); || structured.alphaTest == GFXS_ALPHA_TEST_GE_128);
if (structured.alphaTestDisabled) if (structured.alphaTestDisabled)
jStateBitsTableEntry.alphaTest = JsonAlphaTest::DISABLED; jStateBitsTableEntry.alphaTest = JsonAlphaTest::DISABLED;
else if (structured.alphaTest == GFXS_ALPHA_TEST_GT_0) else if (structured.alphaTest == GFXS_ALPHA_TEST_GT_0)
jStateBitsTableEntry.alphaTest = JsonAlphaTest::GT0; jStateBitsTableEntry.alphaTest = JsonAlphaTest::GT0;
#if defined(FEATURE_IW4) || defined(FEATURE_IW5) #if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5)
else if (structured.alphaTest == GFXS_ALPHA_TEST_LT_128) else if (structured.alphaTest == GFXS_ALPHA_TEST_LT_128)
jStateBitsTableEntry.alphaTest = JsonAlphaTest::LT128; jStateBitsTableEntry.alphaTest = JsonAlphaTest::LT128;
#elif defined(FEATURE_T5)
else if (structured.alphaTest == GFXS_ALPHA_TEST_GE_255)
jStateBitsTableEntry.alphaTest = JsonAlphaTest::GE255;
#endif #endif
else if (structured.alphaTest == GFXS_ALPHA_TEST_GE_128) else if (structured.alphaTest == GFXS_ALPHA_TEST_GE_128)
jStateBitsTableEntry.alphaTest = JsonAlphaTest::GE128; jStateBitsTableEntry.alphaTest = JsonAlphaTest::GE128;
@@ -300,9 +314,10 @@ namespace
jMaterial.textureAtlas->columns = material.info.textureAtlasColumnCount; jMaterial.textureAtlas->columns = material.info.textureAtlasColumnCount;
jMaterial.surfaceTypeBits = material.info.surfaceTypeBits; jMaterial.surfaceTypeBits = material.info.surfaceTypeBits;
#ifdef FEATURE_T6 #if defined(FEATURE_T5) || defined(FEATURE_T6)
jMaterial.layeredSurfaceTypes = material.info.layeredSurfaceTypes; jMaterial.layeredSurfaceTypes = material.info.layeredSurfaceTypes;
jMaterial.hashIndex = material.info.hashIndex; #endif
#if defined(FEATURE_T6)
jMaterial.surfaceFlags = material.info.surfaceFlags; jMaterial.surfaceFlags = material.info.surfaceFlags;
jMaterial.contents = material.info.contents; jMaterial.contents = material.info.contents;
#endif #endif
@@ -313,9 +328,6 @@ namespace
jMaterial.stateFlags = material.stateFlags; jMaterial.stateFlags = material.stateFlags;
jMaterial.cameraRegion = static_cast<GfxCameraRegionType>(material.cameraRegion); jMaterial.cameraRegion = static_cast<GfxCameraRegionType>(material.cameraRegion);
#ifdef FEATURE_T6
jMaterial.probeMipBits = material.probeMipBits;
#endif
if (material.techniqueSet && material.techniqueSet->name) if (material.techniqueSet && material.techniqueSet->name)
jMaterial.techniqueSet = AssetName(material.techniqueSet->name); jMaterial.techniqueSet = AssetName(material.techniqueSet->name);

View File

@@ -1,4 +1,4 @@
#options GAME (IW4, IW5, T6) #options GAME (IW3, IW4, IW5, T5, T6)
#filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".h" #filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".h"

View File

@@ -14,9 +14,6 @@ public:
std::unique_ptr<AssetPool<IW3::XAnimParts>> m_xanim_parts; std::unique_ptr<AssetPool<IW3::XAnimParts>> m_xanim_parts;
std::unique_ptr<AssetPool<IW3::XModel>> m_xmodel; std::unique_ptr<AssetPool<IW3::XModel>> m_xmodel;
std::unique_ptr<AssetPool<IW3::Material>> m_material; std::unique_ptr<AssetPool<IW3::Material>> m_material;
std::unique_ptr<AssetPool<IW3::MaterialPixelShader>> m_material_pixel_shader;
std::unique_ptr<AssetPool<IW3::MaterialVertexShader>> m_material_vertex_shader;
std::unique_ptr<AssetPool<IW3::MaterialVertexDeclaration>> m_material_vertex_decl;
std::unique_ptr<AssetPool<IW3::MaterialTechniqueSet>> m_technique_set; std::unique_ptr<AssetPool<IW3::MaterialTechniqueSet>> m_technique_set;
std::unique_ptr<AssetPool<IW3::GfxImage>> m_image; std::unique_ptr<AssetPool<IW3::GfxImage>> m_image;
std::unique_ptr<AssetPool<IW3::snd_alias_list_t>> m_sound; std::unique_ptr<AssetPool<IW3::snd_alias_list_t>> m_sound;

View File

@@ -0,0 +1,577 @@
#include "Game/IW3/Material/LoaderMaterialIW3.h"
#include "Game/IW3/CommonIW3.h"
#include "Game/IW3/GameIW3.h"
#include "SearchPath/MockSearchPath.h"
#include "Utils/MemoryManager.h"
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include <string>
using namespace IW3;
using namespace Catch;
using namespace std::literals;
namespace
{
void GivenImage(const std::string& name, AssetCreationContext& context, MemoryManager& memory)
{
auto* image = memory.Alloc<GfxImage>();
image->name = memory.Dup(name.c_str());
AssetRegistration<AssetImage> registration(name);
registration.SetAsset(image);
context.AddAsset(std::move(registration));
}
void GivenTechset(const std::string& name, AssetCreationContext& context, MemoryManager& memory)
{
auto* techset = memory.Alloc<MaterialTechniqueSet>();
techset->name = memory.Dup(name.c_str());
AssetRegistration<AssetTechniqueSet> registration(name);
registration.SetAsset(techset);
context.AddAsset(std::move(registration));
}
TEST_CASE("LoaderMaterial(IW3): Can parse material", "[iw3][material][assetloader]")
{
MockSearchPath searchPath;
searchPath.AddFileData("materials/wc/ch_plasterwall_long.json",
R"MATERIAL(
{
"_game": "iw3",
"_type": "material",
"_version": 1,
"cameraRegion": "lit",
"constants": [
{
"literal": [
0.800000011920929,
2.0,
1.0,
0.625
],
"name": "envMapParms"
},
{
"literal": [
1.0,
1.0,
1.0,
1.0
],
"name": "colorTint"
}
],
"gameFlags": [
"2",
"10",
"CASTS_SHADOW"
],
"sortKey": 4,
"stateBits": [
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "none",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offsetShadowmap",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "none",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "add",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "one",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "invdestalpha",
"stencilFront": {
"fail": "keep",
"func": "equal",
"pass": "keep",
"zfail": "keep"
}
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset2",
"polymodeLine": true,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "add",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "invsrccolor",
"polygonOffset": "offset2",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "zero"
}
],
"stateBitsEntry": [
0,
1,
2,
3,
1,
-1,
-1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
4,
4,
4,
-1,
-1,
-1,
-1,
5,
-1,
1,
6,
1,
-1
],
"stateFlags": 57,
"surfaceTypeBits": 32768,
"techniqueSet": "wc_l_sm_r0c0n0s0",
"textureAtlas": {
"columns": 1,
"rows": 1
},
"textures": [
{
"image": "~ch_plasterwall_long_spc-r-49~3c124bfe",
"name": "specularMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "specularMap"
},
{
"image": "ch_plasterwall_long_nml",
"name": "normalMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "linear"
},
"semantic": "normalMap"
},
{
"image": "ch_plasterwall_long_col",
"name": "colorMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "linear"
},
"semantic": "colorMap"
}
]
})MATERIAL");
Zone zone("MockZone", 0, IGame::GetGameById(GameId::IW3));
MemoryManager memory;
AssetCreatorCollection creatorCollection(zone);
IgnoredAssetLookup ignoredAssetLookup;
AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup);
GivenImage("~ch_plasterwall_long_spc-r-49~3c124bfe", context, memory);
GivenImage("ch_plasterwall_long_nml", context, memory);
GivenImage("ch_plasterwall_long_col", context, memory);
GivenTechset("wc_l_sm_r0c0n0s0", context, memory);
auto loader = CreateMaterialLoader(memory, searchPath);
auto result = loader->CreateAsset("wc/ch_plasterwall_long", context);
REQUIRE(result.HasBeenSuccessful());
const auto* assetInfo = reinterpret_cast<XAssetInfo<Material>*>(result.GetAssetInfo());
const auto* material = assetInfo->Asset();
REQUIRE(material->info.name == "wc/ch_plasterwall_long"s);
REQUIRE(material->info.gameFlags == 0x52);
REQUIRE(material->info.sortKey == 4);
REQUIRE(material->info.textureAtlasRowCount == 1);
REQUIRE(material->info.textureAtlasColumnCount == 1);
REQUIRE(material->info.surfaceTypeBits == 0x8000);
constexpr int8_t expectedStateBitsEntry[]{0, 1, 2, 3, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
-1, -1, -1, -1, 4, 4, 4, -1, -1, -1, -1, 5, -1, 1, 6, 1, -1};
REQUIRE(std::memcmp(material->stateBitsEntry, expectedStateBitsEntry, sizeof(expectedStateBitsEntry)) == 0);
REQUIRE(material->stateFlags == 57);
REQUIRE(material->cameraRegion == CAMERA_REGION_LIT);
REQUIRE(material->techniqueSet != nullptr);
REQUIRE(material->techniqueSet->name != nullptr);
REQUIRE(material->techniqueSet->name == "wc_l_sm_r0c0n0s0"s);
REQUIRE(material->textureCount == 3);
REQUIRE(material->textureTable);
const auto& textureDef0 = material->textureTable[0];
REQUIRE(textureDef0.nameHash == 0x34ecccb3);
REQUIRE(textureDef0.nameStart == 's');
REQUIRE(textureDef0.nameEnd == 'p');
REQUIRE(textureDef0.samplerState.filter == TEXTURE_FILTER_ANISO2X);
REQUIRE(textureDef0.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_NEAREST);
REQUIRE(textureDef0.samplerState.clampU == 0);
REQUIRE(textureDef0.samplerState.clampV == 0);
REQUIRE(textureDef0.samplerState.clampW == 0);
REQUIRE(textureDef0.semantic == TS_SPECULAR_MAP);
REQUIRE(textureDef0.u.image);
REQUIRE(textureDef0.u.image->name);
REQUIRE(textureDef0.u.image->name == "~ch_plasterwall_long_spc-r-49~3c124bfe"s);
const auto& textureDef1 = material->textureTable[1];
REQUIRE(textureDef1.nameHash == 0x59d30d0f);
REQUIRE(textureDef1.nameStart == 'n');
REQUIRE(textureDef1.nameEnd == 'p');
REQUIRE(textureDef1.samplerState.filter == TEXTURE_FILTER_ANISO2X);
REQUIRE(textureDef1.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_LINEAR);
REQUIRE(textureDef1.samplerState.clampU == 0);
REQUIRE(textureDef1.samplerState.clampV == 0);
REQUIRE(textureDef1.samplerState.clampW == 0);
REQUIRE(textureDef1.semantic == TS_NORMAL_MAP);
REQUIRE(textureDef1.u.image);
REQUIRE(textureDef1.u.image->name);
REQUIRE(textureDef1.u.image->name == "ch_plasterwall_long_nml"s);
const auto& textureDef2 = material->textureTable[2];
REQUIRE(textureDef2.nameHash == 0xa0ab1041);
REQUIRE(textureDef2.nameStart == 'c');
REQUIRE(textureDef2.nameEnd == 'p');
REQUIRE(textureDef2.samplerState.filter == TEXTURE_FILTER_ANISO2X);
REQUIRE(textureDef2.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_LINEAR);
REQUIRE(textureDef2.samplerState.clampU == 0);
REQUIRE(textureDef2.samplerState.clampV == 0);
REQUIRE(textureDef2.samplerState.clampW == 0);
REQUIRE(textureDef2.semantic == TS_COLOR_MAP);
REQUIRE(textureDef2.u.image);
REQUIRE(textureDef2.u.image->name);
REQUIRE(textureDef2.u.image->name == "ch_plasterwall_long_col"s);
REQUIRE(material->constantCount == 2);
REQUIRE(material->constantTable);
const auto& constantDef0 = material->constantTable[0];
REQUIRE(constantDef0.nameHash == 0x3d9994dc);
REQUIRE(strncmp(constantDef0.name, "envMapParms", std::extent_v<decltype(MaterialConstantDef::name)>) == 0);
REQUIRE(constantDef0.literal.x == Approx(0.8f));
REQUIRE(constantDef0.literal.y == Approx(2.0f));
REQUIRE(constantDef0.literal.z == Approx(1.0f));
REQUIRE(constantDef0.literal.w == Approx(0.625f));
const auto& constantDef1 = material->constantTable[1];
REQUIRE(constantDef1.nameHash == 0xb60c3b3a);
REQUIRE(strncmp(constantDef1.name, "colorTint", std::extent_v<decltype(MaterialConstantDef::name)>) == 0);
REQUIRE(constantDef1.literal.x == Approx(1.0f));
REQUIRE(constantDef1.literal.y == Approx(1.0f));
REQUIRE(constantDef1.literal.z == Approx(1.0f));
REQUIRE(constantDef1.literal.w == Approx(1.0f));
REQUIRE(material->stateBitsCount == 7);
REQUIRE(material->stateBitsTable);
const auto& stateBits0 = material->stateBitsTable[0];
REQUIRE(stateBits0.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits0.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits0.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits0.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits0.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits0.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits0.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits0.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits0.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits0.loadBits.structured.colorWriteRgb == 0);
REQUIRE(stateBits0.loadBits.structured.colorWriteAlpha == 0);
REQUIRE(stateBits0.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits0.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits0.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits0.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits0.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits0.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits0.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits0.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits0.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits0.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits1 = material->stateBitsTable[1];
REQUIRE(stateBits1.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits1.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits1.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits1.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits1.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits1.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits1.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits1.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits1.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits1.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits1.loadBits.structured.colorWriteAlpha == 1);
REQUIRE(stateBits1.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits1.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits1.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits1.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits1.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits2 = material->stateBitsTable[2];
REQUIRE(stateBits2.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits2.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits2.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits2.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits2.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits2.loadBits.structured.cullFace == GFXS_CULL_NONE);
REQUIRE(stateBits2.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits2.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits2.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits2.loadBits.structured.colorWriteRgb == 0);
REQUIRE(stateBits2.loadBits.structured.colorWriteAlpha == 0);
REQUIRE(stateBits2.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits2.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits2.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits2.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits2.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_SHADOWMAP);
REQUIRE(stateBits2.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits3 = material->stateBitsTable[3];
REQUIRE(stateBits3.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits3.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits3.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits3.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits3.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits3.loadBits.structured.cullFace == GFXS_CULL_NONE);
REQUIRE(stateBits3.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits3.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits3.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits3.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits3.loadBits.structured.colorWriteAlpha == 1);
REQUIRE(stateBits3.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits3.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits3.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits3.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits3.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits4 = material->stateBitsTable[4];
REQUIRE(stateBits4.loadBits.structured.srcBlendRgb == GFXS_BLEND_INVDESTALPHA);
REQUIRE(stateBits4.loadBits.structured.dstBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits4.loadBits.structured.blendOpRgb == GFXS_BLENDOP_ADD);
REQUIRE(stateBits4.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits4.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits4.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits4.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits4.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits4.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits4.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits4.loadBits.structured.colorWriteAlpha == 1);
REQUIRE(stateBits4.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits4.loadBits.structured.depthWrite == 0);
REQUIRE(stateBits4.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits4.loadBits.structured.depthTest == GFXS_DEPTHTEST_EQUAL);
REQUIRE(stateBits4.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits4.loadBits.structured.stencilFrontEnabled == 1);
REQUIRE(stateBits4.loadBits.structured.stencilFrontPass == GFXS_STENCILOP_KEEP);
REQUIRE(stateBits4.loadBits.structured.stencilFrontFail == GFXS_STENCILOP_KEEP);
REQUIRE(stateBits4.loadBits.structured.stencilFrontZFail == GFXS_STENCILOP_KEEP);
REQUIRE(stateBits4.loadBits.structured.stencilFrontFunc == GFXS_STENCILFUNC_EQUAL);
REQUIRE(stateBits4.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits5 = material->stateBitsTable[5];
REQUIRE(stateBits5.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits5.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits5.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits5.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits5.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits5.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits5.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits5.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits5.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits5.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits5.loadBits.structured.colorWriteAlpha == 0);
REQUIRE(stateBits5.loadBits.structured.polymodeLine == 1);
REQUIRE(stateBits5.loadBits.structured.depthWrite == 0);
REQUIRE(stateBits5.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits5.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits5.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_2);
REQUIRE(stateBits5.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits6 = material->stateBitsTable[6];
REQUIRE(stateBits6.loadBits.structured.srcBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits6.loadBits.structured.dstBlendRgb == GFXS_BLEND_INVSRCCOLOR);
REQUIRE(stateBits6.loadBits.structured.blendOpRgb == GFXS_BLENDOP_ADD);
REQUIRE(stateBits6.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits6.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits6.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits6.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits6.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits6.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits6.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits6.loadBits.structured.colorWriteAlpha == 1);
REQUIRE(stateBits6.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits6.loadBits.structured.depthWrite == 0);
REQUIRE(stateBits6.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits6.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits6.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_2);
REQUIRE(stateBits6.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits6.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits6.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits6.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits6.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits6.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits6.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits6.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits6.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits6.loadBits.structured.stencilBackFunc == 0);
}
} // namespace

View File

@@ -0,0 +1,640 @@
#include "Game/T5/Material/LoaderMaterialT5.h"
#include "Game/T5/CommonT5.h"
#include "Game/T5/GameT5.h"
#include "SearchPath/MockSearchPath.h"
#include "Utils/MemoryManager.h"
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include <string>
using namespace T5;
using namespace Catch;
using namespace std::literals;
namespace
{
void GivenImage(const std::string& name, AssetCreationContext& context, MemoryManager& memory)
{
auto* image = memory.Alloc<GfxImage>();
image->name = memory.Dup(name.c_str());
AssetRegistration<AssetImage> registration(name);
registration.SetAsset(image);
context.AddAsset(std::move(registration));
}
void GivenTechset(const std::string& name, AssetCreationContext& context, MemoryManager& memory)
{
auto* techset = memory.Alloc<MaterialTechniqueSet>();
techset->name = memory.Dup(name.c_str());
AssetRegistration<AssetTechniqueSet> registration(name);
registration.SetAsset(techset);
context.AddAsset(std::move(registration));
}
TEST_CASE("LoaderMaterial(T5): Can parse material", "[t5][material][assetloader]")
{
MockSearchPath searchPath;
searchPath.AddFileData("materials/mc/jun_art_brick_foundation.json",
R"MATERIAL(
{
"_game": "t5",
"_type": "material",
"_version": 1,
"cameraRegion": "lit",
"constants": [
{
"literal": [
1.0,
1.0,
1.0,
0.5
],
"name": "envMapParms"
},
{
"literal": [
0.0,
1.0,
0.0,
1.0
],
"nameFragment": "dynamicFolia",
"nameHash": 3034467714
}
],
"gameFlags": [
"10",
"CASTS_SHADOW"
],
"layeredSurfaceTypes": 536870914,
"sortKey": 4,
"stateBits": [
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one",
"stencilFront": {
"fail": "keep",
"func": "equal",
"pass": "keep",
"zfail": "keep"
}
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offsetShadowmap",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "none",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "add",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "one",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "invdestalpha"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset2",
"polymodeLine": true,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
}
],
"stateBitsEntry": [
0,
1,
2,
3,
1,
-1,
-1,
-1,
-1,
-1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
4,
4,
4,
4,
4,
4,
-1,
-1,
-1,
-1,
5,
-1,
1,
1,
-1
],
"stateFlags": 121,
"surfaceTypeBits": 2,
"techniqueSet": "mc_l_sm_r0c0n0s0",
"textureAtlas": {
"columns": 1,
"rows": 1
},
"textures": [
{
"image": "~$white-rgb&~-rjun_art_brick_~a05e7627",
"isMatureContent": false,
"name": "specularMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "specularMap"
},
{
"image": "jun_art_brick_foundation_n",
"isMatureContent": false,
"name": "normalMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "normalMap"
},
{
"image": "~-gjun_art_brick_foundation_c",
"isMatureContent": false,
"name": "colorMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "colorMap"
}
]
})MATERIAL");
Zone zone("MockZone", 0, IGame::GetGameById(GameId::T5));
MemoryManager memory;
AssetCreatorCollection creatorCollection(zone);
IgnoredAssetLookup ignoredAssetLookup;
AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup);
GivenImage("~$white-rgb&~-rjun_art_brick_~a05e7627", context, memory);
GivenImage("jun_art_brick_foundation_n", context, memory);
GivenImage("~-gjun_art_brick_foundation_c", context, memory);
GivenTechset("mc_l_sm_r0c0n0s0", context, memory);
auto loader = CreateMaterialLoader(memory, searchPath);
auto result = loader->CreateAsset("mc/jun_art_brick_foundation", context);
REQUIRE(result.HasBeenSuccessful());
const auto* assetInfo = reinterpret_cast<XAssetInfo<Material>*>(result.GetAssetInfo());
const auto* material = assetInfo->Asset();
REQUIRE(material->info.name == "mc/jun_art_brick_foundation"s);
REQUIRE(material->info.gameFlags == 0x50);
REQUIRE(material->info.sortKey == 4);
REQUIRE(material->info.textureAtlasRowCount == 1);
REQUIRE(material->info.textureAtlasColumnCount == 1);
REQUIRE(material->info.surfaceTypeBits == 0x2);
REQUIRE(material->info.layeredSurfaceTypes == 0x20000002);
constexpr int8_t expectedStateBitsEntry[]{0, 1, 2, 3, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1,
1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 4, 4, 4, 4, 4, -1, -1, -1, -1, 5, -1, 1, 1, -1};
REQUIRE(std::memcmp(material->stateBitsEntry, expectedStateBitsEntry, sizeof(expectedStateBitsEntry)) == 0);
REQUIRE(material->stateFlags == 121);
REQUIRE(material->cameraRegion == CAMERA_REGION_LIT);
REQUIRE(material->techniqueSet != nullptr);
REQUIRE(material->techniqueSet->name != nullptr);
REQUIRE(material->techniqueSet->name == "mc_l_sm_r0c0n0s0"s);
REQUIRE(material->textureCount == 3);
REQUIRE(material->textureTable);
const auto& textureDef0 = material->textureTable[0];
REQUIRE(textureDef0.nameHash == 0x34ecccb3);
REQUIRE(textureDef0.nameStart == 's');
REQUIRE(textureDef0.nameEnd == 'p');
REQUIRE(textureDef0.samplerState.filter == TEXTURE_FILTER_ANISO2X);
REQUIRE(textureDef0.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_NEAREST);
REQUIRE(textureDef0.samplerState.clampU == 0);
REQUIRE(textureDef0.samplerState.clampV == 0);
REQUIRE(textureDef0.samplerState.clampW == 0);
REQUIRE(textureDef0.semantic == TS_SPECULAR_MAP);
REQUIRE(textureDef0.isMatureContent == false);
REQUIRE(textureDef0.u.image);
REQUIRE(textureDef0.u.image->name);
REQUIRE(textureDef0.u.image->name == "~$white-rgb&~-rjun_art_brick_~a05e7627"s);
const auto& textureDef1 = material->textureTable[1];
REQUIRE(textureDef1.nameHash == 0x59d30d0f);
REQUIRE(textureDef1.nameStart == 'n');
REQUIRE(textureDef1.nameEnd == 'p');
REQUIRE(textureDef1.samplerState.filter == TEXTURE_FILTER_ANISO2X);
REQUIRE(textureDef1.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_NEAREST);
REQUIRE(textureDef1.samplerState.clampU == 0);
REQUIRE(textureDef1.samplerState.clampV == 0);
REQUIRE(textureDef1.samplerState.clampW == 0);
REQUIRE(textureDef1.semantic == TS_NORMAL_MAP);
REQUIRE(textureDef1.isMatureContent == false);
REQUIRE(textureDef1.u.image);
REQUIRE(textureDef1.u.image->name);
REQUIRE(textureDef1.u.image->name == "jun_art_brick_foundation_n"s);
const auto& textureDef2 = material->textureTable[2];
REQUIRE(textureDef2.nameHash == 0xa0ab1041);
REQUIRE(textureDef2.nameStart == 'c');
REQUIRE(textureDef2.nameEnd == 'p');
REQUIRE(textureDef2.samplerState.filter == TEXTURE_FILTER_ANISO2X);
REQUIRE(textureDef2.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_NEAREST);
REQUIRE(textureDef2.samplerState.clampU == 0);
REQUIRE(textureDef2.samplerState.clampV == 0);
REQUIRE(textureDef2.samplerState.clampW == 0);
REQUIRE(textureDef2.semantic == TS_COLOR_MAP);
REQUIRE(textureDef2.isMatureContent == false);
REQUIRE(textureDef2.u.image);
REQUIRE(textureDef2.u.image->name);
REQUIRE(textureDef2.u.image->name == "~-gjun_art_brick_foundation_c"s);
REQUIRE(material->constantCount == 2);
REQUIRE(material->constantTable);
const auto& constantDef0 = material->constantTable[0];
REQUIRE(constantDef0.nameHash == 0x3d9994dc);
REQUIRE(strncmp(constantDef0.name, "envMapParms", std::extent_v<decltype(MaterialConstantDef::name)>) == 0);
REQUIRE(constantDef0.literal.x == Approx(1.0f));
REQUIRE(constantDef0.literal.y == Approx(1.0f));
REQUIRE(constantDef0.literal.z == Approx(1.0f));
REQUIRE(constantDef0.literal.w == Approx(0.5f));
const auto& constantDef1 = material->constantTable[1];
REQUIRE(constantDef1.nameHash == 0xb4de4d82);
REQUIRE(strncmp(constantDef1.name, "dynamicFolia", std::extent_v<decltype(MaterialConstantDef::name)>) == 0);
REQUIRE(constantDef1.literal.x == Approx(0.0f));
REQUIRE(constantDef1.literal.y == Approx(1.0f));
REQUIRE(constantDef1.literal.z == Approx(0.0f));
REQUIRE(constantDef1.literal.w == Approx(1.0f));
REQUIRE(material->stateBitsCount == 6);
REQUIRE(material->stateBitsTable);
const auto& stateBits0 = material->stateBitsTable[0];
REQUIRE(stateBits0.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits0.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits0.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits0.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits0.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits0.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits0.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits0.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits0.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits0.loadBits.structured.colorWriteRgb == 0);
REQUIRE(stateBits0.loadBits.structured.colorWriteAlpha == 0);
REQUIRE(stateBits0.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits0.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits0.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits0.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits0.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits0.loadBits.structured.stencilFrontEnabled == 1);
REQUIRE(stateBits0.loadBits.structured.stencilFrontPass == GFXS_STENCILOP_KEEP);
REQUIRE(stateBits0.loadBits.structured.stencilFrontFail == GFXS_STENCILOP_KEEP);
REQUIRE(stateBits0.loadBits.structured.stencilFrontZFail == GFXS_STENCILOP_KEEP);
REQUIRE(stateBits0.loadBits.structured.stencilFrontFunc == GFXS_STENCILFUNC_EQUAL);
REQUIRE(stateBits0.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits0.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits1 = material->stateBitsTable[1];
REQUIRE(stateBits1.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits1.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits1.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits1.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits1.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits1.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits1.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits1.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits1.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits1.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits1.loadBits.structured.colorWriteAlpha == 1);
REQUIRE(stateBits1.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits1.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits1.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits1.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits1.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits1.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits2 = material->stateBitsTable[2];
REQUIRE(stateBits2.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits2.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits2.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits2.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits2.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits2.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits2.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits2.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits2.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits2.loadBits.structured.colorWriteRgb == 0);
REQUIRE(stateBits2.loadBits.structured.colorWriteAlpha == 0);
REQUIRE(stateBits2.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits2.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits2.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits2.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits2.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_SHADOWMAP);
REQUIRE(stateBits2.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits2.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits3 = material->stateBitsTable[3];
REQUIRE(stateBits3.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits3.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits3.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits3.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits3.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits3.loadBits.structured.cullFace == GFXS_CULL_NONE);
REQUIRE(stateBits3.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits3.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits3.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits3.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits3.loadBits.structured.colorWriteAlpha == 1);
REQUIRE(stateBits3.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits3.loadBits.structured.depthWrite == 1);
REQUIRE(stateBits3.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits3.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits3.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits3.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits4 = material->stateBitsTable[4];
REQUIRE(stateBits4.loadBits.structured.srcBlendRgb == GFXS_BLEND_INVDESTALPHA);
REQUIRE(stateBits4.loadBits.structured.dstBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits4.loadBits.structured.blendOpRgb == GFXS_BLENDOP_ADD);
REQUIRE(stateBits4.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits4.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits4.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits4.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits4.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits4.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits4.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits4.loadBits.structured.colorWriteAlpha == 1);
REQUIRE(stateBits4.loadBits.structured.polymodeLine == 0);
REQUIRE(stateBits4.loadBits.structured.depthWrite == 0);
REQUIRE(stateBits4.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits4.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits4.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0);
REQUIRE(stateBits4.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits4.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits4.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits4.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits4.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits4.loadBits.structured.stencilBackFunc == 0);
const auto& stateBits5 = material->stateBitsTable[5];
REQUIRE(stateBits5.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE);
REQUIRE(stateBits5.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO);
REQUIRE(stateBits5.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits5.loadBits.structured.alphaTestDisabled == 1);
REQUIRE(stateBits5.loadBits.structured.alphaTest == 0);
REQUIRE(stateBits5.loadBits.structured.cullFace == GFXS_CULL_BACK);
REQUIRE(stateBits5.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE);
REQUIRE(stateBits5.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO);
REQUIRE(stateBits5.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED);
REQUIRE(stateBits5.loadBits.structured.colorWriteRgb == 1);
REQUIRE(stateBits5.loadBits.structured.colorWriteAlpha == 0);
REQUIRE(stateBits5.loadBits.structured.polymodeLine == 1);
REQUIRE(stateBits5.loadBits.structured.depthWrite == 0);
REQUIRE(stateBits5.loadBits.structured.depthTestDisabled == 0);
REQUIRE(stateBits5.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
REQUIRE(stateBits5.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_2);
REQUIRE(stateBits5.loadBits.structured.stencilFrontEnabled == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontPass == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontZFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilFrontFunc == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackEnabled == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackPass == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackZFail == 0);
REQUIRE(stateBits5.loadBits.structured.stencilBackFunc == 0);
}
} // namespace

View File

@@ -62,9 +62,7 @@ namespace
"10", "10",
"CASTS_SHADOW" "CASTS_SHADOW"
], ],
"hashIndex": 0,
"layeredSurfaceTypes": 536870925, "layeredSurfaceTypes": 536870925,
"probeMipBits": 0,
"sortKey": 4, "sortKey": 4,
"stateBits": [ "stateBits": [
{ {

View File

@@ -0,0 +1,572 @@
#include "Game/IW3/Material/DumperMaterialIW3.h"
#include "Asset/AssetRegistration.h"
#include "Game/IW3/CommonIW3.h"
#include "Game/IW3/GameIW3.h"
#include "NormalizedJson.h"
#include "Pool/AssetPoolDynamic.h"
#include "SearchPath/MockOutputPath.h"
#include "SearchPath/MockSearchPath.h"
#include "Utils/MemoryManager.h"
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include <string>
using namespace IW3;
using namespace Catch;
using namespace std::literals;
namespace
{
GfxImage* GivenImage(const std::string& name, MemoryManager& memory)
{
auto* image = memory.Alloc<GfxImage>();
image->name = memory.Dup(name.c_str());
return image;
}
MaterialTechniqueSet* GivenTechset(const std::string& name, MemoryManager& memory)
{
auto* techset = memory.Alloc<MaterialTechniqueSet>();
techset->name = memory.Dup(name.c_str());
return techset;
}
void GivenMaterial(const std::string& name, AssetPool<Material>& pool, MemoryManager& memory)
{
auto* material = memory.Alloc<Material>();
material->info.name = memory.Dup(name.c_str());
material->info.gameFlags = 0x52;
material->info.sortKey = 4;
material->info.textureAtlasRowCount = 1;
material->info.textureAtlasColumnCount = 1;
material->info.surfaceTypeBits = 0x8000;
constexpr int8_t stateBitsEntry[] = {0, 1, 2, 3, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
-1, -1, -1, -1, 4, 4, 4, -1, -1, -1, -1, 5, -1, 1, 6, 1, -1};
std::memcpy(material->stateBitsEntry, stateBitsEntry, sizeof(material->stateBitsEntry));
material->cameraRegion = CAMERA_REGION_LIT;
material->stateFlags = 57;
material->techniqueSet = GivenTechset("wc_l_sm_r0c0n0s0", memory);
material->textureCount = 3;
material->textureTable = memory.Alloc<MaterialTextureDef>(3);
auto& textureDef0 = material->textureTable[0];
textureDef0.u.image = GivenImage("~ch_plasterwall_long_spc-r-49~3c124bfe", memory);
textureDef0.nameHash = 0x34ecccb3;
textureDef0.nameStart = 's';
textureDef0.nameEnd = 'p';
textureDef0.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef0.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef0.samplerState.clampU = 0;
textureDef0.samplerState.clampV = 0;
textureDef0.samplerState.clampW = 0;
textureDef0.semantic = TS_SPECULAR_MAP;
auto& textureDef1 = material->textureTable[1];
textureDef1.u.image = GivenImage("ch_plasterwall_long_nml", memory);
textureDef1.nameHash = 0x59d30d0f;
textureDef1.nameStart = 'n';
textureDef1.nameEnd = 'p';
textureDef1.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef1.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_LINEAR;
textureDef1.samplerState.clampU = 0;
textureDef1.samplerState.clampV = 0;
textureDef1.samplerState.clampW = 0;
textureDef1.semantic = TS_NORMAL_MAP;
auto& textureDef2 = material->textureTable[2];
textureDef2.u.image = GivenImage("ch_plasterwall_long_col", memory);
textureDef2.nameHash = 0xa0ab1041;
textureDef2.nameStart = 'c';
textureDef2.nameEnd = 'p';
textureDef2.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef2.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_LINEAR;
textureDef2.samplerState.clampU = 0;
textureDef2.samplerState.clampV = 0;
textureDef2.samplerState.clampW = 0;
textureDef2.semantic = TS_COLOR_MAP;
material->constantCount = 2;
material->constantTable = memory.Alloc<MaterialConstantDef>(2);
auto& constantDef0 = material->constantTable[0];
constantDef0.nameHash = 0x3d9994dc;
strncpy(constantDef0.name, "envMapParms", std::extent_v<decltype(MaterialConstantDef::name)>);
constantDef0.literal.x = 0.8f;
constantDef0.literal.y = 2.0f;
constantDef0.literal.z = 1.0f;
constantDef0.literal.w = 0.625f;
auto& constantDef1 = material->constantTable[1];
constantDef1.nameHash = 0xb60c3b3a;
strncpy(constantDef1.name, "colorTint", std::extent_v<decltype(MaterialConstantDef::name)>);
constantDef1.literal.x = 1.0f;
constantDef1.literal.y = 1.0f;
constantDef1.literal.z = 1.0f;
constantDef1.literal.w = 1.0f;
material->stateBitsCount = 7;
material->stateBitsTable = memory.Alloc<GfxStateBits>(7);
auto& stateBits0 = material->stateBitsTable[0];
stateBits0.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits0.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits0.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits0.loadBits.structured.alphaTestDisabled = 1;
stateBits0.loadBits.structured.alphaTest = 0;
stateBits0.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits0.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits0.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits0.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits0.loadBits.structured.colorWriteRgb = 0;
stateBits0.loadBits.structured.colorWriteAlpha = 0;
stateBits0.loadBits.structured.polymodeLine = 0;
stateBits0.loadBits.structured.depthWrite = 1;
stateBits0.loadBits.structured.depthTestDisabled = 0;
stateBits0.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits0.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits0.loadBits.structured.stencilFrontEnabled = 0;
stateBits0.loadBits.structured.stencilFrontPass = 0;
stateBits0.loadBits.structured.stencilFrontFail = 0;
stateBits0.loadBits.structured.stencilFrontZFail = 0;
stateBits0.loadBits.structured.stencilFrontFunc = 0;
stateBits0.loadBits.structured.stencilBackEnabled = 0;
stateBits0.loadBits.structured.stencilBackPass = 0;
stateBits0.loadBits.structured.stencilBackFail = 0;
stateBits0.loadBits.structured.stencilBackZFail = 0;
stateBits0.loadBits.structured.stencilBackFunc = 0;
auto& stateBits1 = material->stateBitsTable[1];
stateBits1.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits1.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits1.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits1.loadBits.structured.alphaTestDisabled = 1;
stateBits1.loadBits.structured.alphaTest = 0;
stateBits1.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits1.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits1.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits1.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits1.loadBits.structured.colorWriteRgb = 1;
stateBits1.loadBits.structured.colorWriteAlpha = 1;
stateBits1.loadBits.structured.polymodeLine = 0;
stateBits1.loadBits.structured.depthWrite = 1;
stateBits1.loadBits.structured.depthTestDisabled = 0;
stateBits1.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits1.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits1.loadBits.structured.stencilFrontEnabled = 0;
stateBits1.loadBits.structured.stencilFrontPass = 0;
stateBits1.loadBits.structured.stencilFrontFail = 0;
stateBits1.loadBits.structured.stencilFrontZFail = 0;
stateBits1.loadBits.structured.stencilFrontFunc = 0;
stateBits1.loadBits.structured.stencilBackEnabled = 0;
stateBits1.loadBits.structured.stencilBackPass = 0;
stateBits1.loadBits.structured.stencilBackFail = 0;
stateBits1.loadBits.structured.stencilBackZFail = 0;
stateBits1.loadBits.structured.stencilBackFunc = 0;
auto& stateBits2 = material->stateBitsTable[2];
stateBits2.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits2.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits2.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits2.loadBits.structured.alphaTestDisabled = 1;
stateBits2.loadBits.structured.alphaTest = 0;
stateBits2.loadBits.structured.cullFace = GFXS_CULL_NONE;
stateBits2.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits2.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits2.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits2.loadBits.structured.colorWriteRgb = 0;
stateBits2.loadBits.structured.colorWriteAlpha = 0;
stateBits2.loadBits.structured.polymodeLine = 0;
stateBits2.loadBits.structured.depthWrite = 1;
stateBits2.loadBits.structured.depthTestDisabled = 0;
stateBits2.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits2.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_SHADOWMAP;
stateBits2.loadBits.structured.stencilFrontEnabled = 0;
stateBits2.loadBits.structured.stencilFrontPass = 0;
stateBits2.loadBits.structured.stencilFrontFail = 0;
stateBits2.loadBits.structured.stencilFrontZFail = 0;
stateBits2.loadBits.structured.stencilFrontFunc = 0;
stateBits2.loadBits.structured.stencilBackEnabled = 0;
stateBits2.loadBits.structured.stencilBackPass = 0;
stateBits2.loadBits.structured.stencilBackFail = 0;
stateBits2.loadBits.structured.stencilBackZFail = 0;
stateBits2.loadBits.structured.stencilBackFunc = 0;
auto& stateBits3 = material->stateBitsTable[3];
stateBits3.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits3.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits3.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits3.loadBits.structured.alphaTestDisabled = 1;
stateBits3.loadBits.structured.alphaTest = 0;
stateBits3.loadBits.structured.cullFace = GFXS_CULL_NONE;
stateBits3.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits3.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits3.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits3.loadBits.structured.colorWriteRgb = 1;
stateBits3.loadBits.structured.colorWriteAlpha = 1;
stateBits3.loadBits.structured.polymodeLine = 0;
stateBits3.loadBits.structured.depthWrite = 1;
stateBits3.loadBits.structured.depthTestDisabled = 0;
stateBits3.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits3.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits3.loadBits.structured.stencilFrontEnabled = 0;
stateBits3.loadBits.structured.stencilFrontPass = 0;
stateBits3.loadBits.structured.stencilFrontFail = 0;
stateBits3.loadBits.structured.stencilFrontZFail = 0;
stateBits3.loadBits.structured.stencilFrontFunc = 0;
stateBits3.loadBits.structured.stencilBackEnabled = 0;
stateBits3.loadBits.structured.stencilBackPass = 0;
stateBits3.loadBits.structured.stencilBackFail = 0;
stateBits3.loadBits.structured.stencilBackZFail = 0;
stateBits3.loadBits.structured.stencilBackFunc = 0;
auto& stateBits4 = material->stateBitsTable[4];
stateBits4.loadBits.structured.srcBlendRgb = GFXS_BLEND_INVDESTALPHA;
stateBits4.loadBits.structured.dstBlendRgb = GFXS_BLEND_ONE;
stateBits4.loadBits.structured.blendOpRgb = GFXS_BLENDOP_ADD;
stateBits4.loadBits.structured.alphaTestDisabled = 1;
stateBits4.loadBits.structured.alphaTest = 0;
stateBits4.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits4.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits4.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits4.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits4.loadBits.structured.colorWriteRgb = 1;
stateBits4.loadBits.structured.colorWriteAlpha = 1;
stateBits4.loadBits.structured.polymodeLine = 0;
stateBits4.loadBits.structured.depthWrite = 0;
stateBits4.loadBits.structured.depthTestDisabled = 0;
stateBits4.loadBits.structured.depthTest = GFXS_DEPTHTEST_EQUAL;
stateBits4.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits4.loadBits.structured.stencilFrontEnabled = 1;
stateBits4.loadBits.structured.stencilFrontPass = GFXS_STENCILOP_KEEP;
stateBits4.loadBits.structured.stencilFrontFail = GFXS_STENCILOP_KEEP;
stateBits4.loadBits.structured.stencilFrontZFail = GFXS_STENCILOP_KEEP;
stateBits4.loadBits.structured.stencilFrontFunc = GFXS_STENCILFUNC_EQUAL;
stateBits4.loadBits.structured.stencilBackEnabled = 0;
stateBits4.loadBits.structured.stencilBackPass = 0;
stateBits4.loadBits.structured.stencilBackFail = 0;
stateBits4.loadBits.structured.stencilBackZFail = 0;
stateBits4.loadBits.structured.stencilBackFunc = 0;
auto& stateBits5 = material->stateBitsTable[5];
stateBits5.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits5.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits5.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits5.loadBits.structured.alphaTestDisabled = 1;
stateBits5.loadBits.structured.alphaTest = 0;
stateBits5.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits5.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits5.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits5.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits5.loadBits.structured.colorWriteRgb = 1;
stateBits5.loadBits.structured.colorWriteAlpha = 0;
stateBits5.loadBits.structured.polymodeLine = 1;
stateBits5.loadBits.structured.depthWrite = 0;
stateBits5.loadBits.structured.depthTestDisabled = 0;
stateBits5.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits5.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_2;
stateBits5.loadBits.structured.stencilFrontEnabled = 0;
stateBits5.loadBits.structured.stencilFrontPass = 0;
stateBits5.loadBits.structured.stencilFrontFail = 0;
stateBits5.loadBits.structured.stencilFrontZFail = 0;
stateBits5.loadBits.structured.stencilFrontFunc = 0;
stateBits5.loadBits.structured.stencilBackEnabled = 0;
stateBits5.loadBits.structured.stencilBackPass = 0;
stateBits5.loadBits.structured.stencilBackFail = 0;
stateBits5.loadBits.structured.stencilBackZFail = 0;
stateBits5.loadBits.structured.stencilBackFunc = 0;
auto& stateBits6 = material->stateBitsTable[6];
stateBits6.loadBits.structured.srcBlendRgb = GFXS_BLEND_ZERO;
stateBits6.loadBits.structured.dstBlendRgb = GFXS_BLEND_INVSRCCOLOR;
stateBits6.loadBits.structured.blendOpRgb = GFXS_BLENDOP_ADD;
stateBits6.loadBits.structured.alphaTestDisabled = 1;
stateBits6.loadBits.structured.alphaTest = 0;
stateBits6.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits6.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits6.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits6.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits6.loadBits.structured.colorWriteRgb = 1;
stateBits6.loadBits.structured.colorWriteAlpha = 1;
stateBits6.loadBits.structured.polymodeLine = 0;
stateBits6.loadBits.structured.depthWrite = 0;
stateBits6.loadBits.structured.depthTestDisabled = 0;
stateBits6.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits6.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_2;
stateBits6.loadBits.structured.stencilFrontEnabled = 0;
stateBits6.loadBits.structured.stencilFrontPass = 0;
stateBits6.loadBits.structured.stencilFrontFail = 0;
stateBits6.loadBits.structured.stencilFrontZFail = 0;
stateBits6.loadBits.structured.stencilFrontFunc = 0;
stateBits6.loadBits.structured.stencilBackEnabled = 0;
stateBits6.loadBits.structured.stencilBackPass = 0;
stateBits6.loadBits.structured.stencilBackFail = 0;
stateBits6.loadBits.structured.stencilBackZFail = 0;
stateBits6.loadBits.structured.stencilBackFunc = 0;
pool.AddAsset(std::make_unique<XAssetInfo<Material>>(ASSET_TYPE_MATERIAL, name, material));
}
TEST_CASE("DumperMaterial(IW3): Can dump material", "[iw3][material][assetdumper]")
{
std::string expected(R"MATERIAL(
{
"$schema": "http://openassettools.dev/schema/material.v1.json",
"_game": "iw3",
"_type": "material",
"_version": 1,
"cameraRegion": "lit",
"constants": [
{
"literal": [
0.800000011920929,
2.0,
1.0,
0.625
],
"name": "envMapParms"
},
{
"literal": [
1.0,
1.0,
1.0,
1.0
],
"name": "colorTint"
}
],
"gameFlags": [
"2",
"10",
"CASTS_SHADOW"
],
"sortKey": 4,
"stateBits": [
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "none",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offsetShadowmap",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "none",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "add",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "one",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "invdestalpha",
"stencilFront": {
"fail": "keep",
"func": "equal",
"pass": "keep",
"zfail": "keep"
}
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset2",
"polymodeLine": true,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "add",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "invsrccolor",
"polygonOffset": "offset2",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "zero"
}
],
"stateBitsEntry": [
0,
1,
2,
3,
1,
-1,
-1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
4,
4,
4,
-1,
-1,
-1,
-1,
5,
-1,
1,
6,
1,
-1
],
"stateFlags": 57,
"surfaceTypeBits": 32768,
"techniqueSet": "wc_l_sm_r0c0n0s0",
"textureAtlas": {
"columns": 1,
"rows": 1
},
"textures": [
{
"image": "~ch_plasterwall_long_spc-r-49~3c124bfe",
"name": "specularMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "specularMap"
},
{
"image": "ch_plasterwall_long_nml",
"name": "normalMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "linear"
},
"semantic": "normalMap"
},
{
"image": "ch_plasterwall_long_col",
"name": "colorMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "linear"
},
"semantic": "colorMap"
}
]
})MATERIAL");
Zone zone("MockZone", 0, IGame::GetGameById(GameId::IW3));
MemoryManager memory;
MockSearchPath mockObjPath;
MockOutputPath mockOutput;
AssetDumpingContext context(zone, "", mockOutput, mockObjPath);
AssetPoolDynamic<Material> materialPool(0);
GivenMaterial("wc/ch_plasterwall_long", materialPool, memory);
AssetDumperMaterial dumper;
dumper.DumpPool(context, &materialPool);
const auto* file = mockOutput.GetMockedFile("materials/wc/ch_plasterwall_long.json");
REQUIRE(file);
REQUIRE(JsonNormalized(file->AsString()) == JsonNormalized(expected));
}
} // namespace

View File

@@ -62,7 +62,7 @@ namespace
textureDef0.nameStart = 's'; textureDef0.nameStart = 's';
textureDef0.nameEnd = 'p'; textureDef0.nameEnd = 'p';
textureDef0.samplerState.filter = TEXTURE_FILTER_ANISO2X; textureDef0.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef0.samplerState.mipMap = TEXTURE_FILTER_NEAREST; textureDef0.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef0.samplerState.clampU = 0; textureDef0.samplerState.clampU = 0;
textureDef0.samplerState.clampV = 0; textureDef0.samplerState.clampV = 0;
textureDef0.samplerState.clampW = 0; textureDef0.samplerState.clampW = 0;
@@ -74,7 +74,7 @@ namespace
textureDef1.nameStart = 'n'; textureDef1.nameStart = 'n';
textureDef1.nameEnd = 'p'; textureDef1.nameEnd = 'p';
textureDef1.samplerState.filter = TEXTURE_FILTER_ANISO2X; textureDef1.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef1.samplerState.mipMap = TEXTURE_FILTER_NEAREST; textureDef1.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef1.samplerState.clampU = 0; textureDef1.samplerState.clampU = 0;
textureDef1.samplerState.clampV = 0; textureDef1.samplerState.clampV = 0;
textureDef1.samplerState.clampW = 0; textureDef1.samplerState.clampW = 0;
@@ -86,7 +86,7 @@ namespace
textureDef2.nameStart = 'c'; textureDef2.nameStart = 'c';
textureDef2.nameEnd = 'p'; textureDef2.nameEnd = 'p';
textureDef2.samplerState.filter = TEXTURE_FILTER_ANISO2X; textureDef2.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef2.samplerState.mipMap = TEXTURE_FILTER_NEAREST; textureDef2.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef2.samplerState.clampU = 0; textureDef2.samplerState.clampU = 0;
textureDef2.samplerState.clampV = 0; textureDef2.samplerState.clampV = 0;
textureDef2.samplerState.clampW = 0; textureDef2.samplerState.clampW = 0;
@@ -295,6 +295,7 @@ namespace
{ {
std::string expected(R"MATERIAL( std::string expected(R"MATERIAL(
{ {
"$schema": "http://openassettools.dev/schema/material.v1.json",
"_game": "iw4", "_game": "iw4",
"_type": "material", "_type": "material",
"_version": 1, "_version": 1,

View File

@@ -62,7 +62,7 @@ namespace
textureDef0.nameStart = 's'; textureDef0.nameStart = 's';
textureDef0.nameEnd = 'p'; textureDef0.nameEnd = 'p';
textureDef0.samplerState.filter = TEXTURE_FILTER_ANISO2X; textureDef0.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef0.samplerState.mipMap = TEXTURE_FILTER_NEAREST; textureDef0.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef0.samplerState.clampU = 0; textureDef0.samplerState.clampU = 0;
textureDef0.samplerState.clampV = 0; textureDef0.samplerState.clampV = 0;
textureDef0.samplerState.clampW = 0; textureDef0.samplerState.clampW = 0;
@@ -74,7 +74,7 @@ namespace
textureDef1.nameStart = 'n'; textureDef1.nameStart = 'n';
textureDef1.nameEnd = 'p'; textureDef1.nameEnd = 'p';
textureDef1.samplerState.filter = TEXTURE_FILTER_ANISO2X; textureDef1.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef1.samplerState.mipMap = TEXTURE_FILTER_LINEAR; textureDef1.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_LINEAR;
textureDef1.samplerState.clampU = 0; textureDef1.samplerState.clampU = 0;
textureDef1.samplerState.clampV = 0; textureDef1.samplerState.clampV = 0;
textureDef1.samplerState.clampW = 0; textureDef1.samplerState.clampW = 0;
@@ -86,7 +86,7 @@ namespace
textureDef2.nameStart = 'c'; textureDef2.nameStart = 'c';
textureDef2.nameEnd = 'p'; textureDef2.nameEnd = 'p';
textureDef2.samplerState.filter = TEXTURE_FILTER_ANISO2X; textureDef2.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef2.samplerState.mipMap = TEXTURE_FILTER_LINEAR; textureDef2.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_LINEAR;
textureDef2.samplerState.clampU = 0; textureDef2.samplerState.clampU = 0;
textureDef2.samplerState.clampV = 0; textureDef2.samplerState.clampV = 0;
textureDef2.samplerState.clampW = 0; textureDef2.samplerState.clampW = 0;
@@ -324,6 +324,7 @@ namespace
{ {
std::string expected(R"MATERIAL( std::string expected(R"MATERIAL(
{ {
"$schema": "http://openassettools.dev/schema/material.v1.json",
"_game": "iw5", "_game": "iw5",
"_type": "material", "_type": "material",
"_version": 1, "_version": 1,

View File

@@ -0,0 +1,635 @@
#include "Game/T5/Material/DumperMaterialT5.h"
#include "Asset/AssetRegistration.h"
#include "Game/T5/CommonT5.h"
#include "Game/T5/GameT5.h"
#include "NormalizedJson.h"
#include "Pool/AssetPoolDynamic.h"
#include "SearchPath/MockOutputPath.h"
#include "SearchPath/MockSearchPath.h"
#include "Utils/MemoryManager.h"
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include <string>
using namespace T5;
using namespace Catch;
using namespace std::literals;
namespace
{
GfxImage* GivenImage(const std::string& name, MemoryManager& memory)
{
auto* image = memory.Alloc<GfxImage>();
image->name = memory.Dup(name.c_str());
return image;
}
MaterialTechniqueSet* GivenTechset(const std::string& name, MemoryManager& memory)
{
auto* techset = memory.Alloc<MaterialTechniqueSet>();
techset->name = memory.Dup(name.c_str());
return techset;
}
void GivenMaterial(const std::string& name, AssetPool<Material>& pool, MemoryManager& memory)
{
auto* material = memory.Alloc<Material>();
material->info.name = memory.Dup(name.c_str());
material->info.gameFlags = 0x50;
material->info.sortKey = 4;
material->info.textureAtlasRowCount = 1;
material->info.textureAtlasColumnCount = 1;
material->info.surfaceTypeBits = 0x2;
material->info.layeredSurfaceTypes = 0x20000002;
constexpr int8_t stateBitsEntry[] = {0, 1, 2, 3, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1,
1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 4, 4, 4, 4, 4, -1, -1, -1, -1, 5, -1, 1, 1, -1};
std::memcpy(material->stateBitsEntry, stateBitsEntry, sizeof(material->stateBitsEntry));
material->cameraRegion = CAMERA_REGION_LIT;
material->stateFlags = 121;
material->techniqueSet = GivenTechset("mc_l_sm_r0c0n0s0", memory);
material->textureCount = 3;
material->textureTable = memory.Alloc<MaterialTextureDef>(3);
auto& textureDef0 = material->textureTable[0];
textureDef0.u.image = GivenImage("~$white-rgb&~-rjun_art_brick_~a05e7627", memory);
textureDef0.nameHash = 0x34ecccb3;
textureDef0.nameStart = 's';
textureDef0.nameEnd = 'p';
textureDef0.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef0.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef0.samplerState.clampU = 0;
textureDef0.samplerState.clampV = 0;
textureDef0.samplerState.clampW = 0;
textureDef0.semantic = TS_SPECULAR_MAP;
textureDef0.isMatureContent = false;
auto& textureDef1 = material->textureTable[1];
textureDef1.u.image = GivenImage("jun_art_brick_foundation_n", memory);
textureDef1.nameHash = 0x59d30d0f;
textureDef1.nameStart = 'n';
textureDef1.nameEnd = 'p';
textureDef1.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef1.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef1.samplerState.clampU = 0;
textureDef1.samplerState.clampV = 0;
textureDef1.samplerState.clampW = 0;
textureDef1.semantic = TS_NORMAL_MAP;
textureDef1.isMatureContent = false;
auto& textureDef2 = material->textureTable[2];
textureDef2.u.image = GivenImage("~-gjun_art_brick_foundation_c", memory);
textureDef2.nameHash = 0xa0ab1041;
textureDef2.nameStart = 'c';
textureDef2.nameEnd = 'p';
textureDef2.samplerState.filter = TEXTURE_FILTER_ANISO2X;
textureDef2.samplerState.mipMap = SAMPLER_MIPMAP_ENUM_NEAREST;
textureDef2.samplerState.clampU = 0;
textureDef2.samplerState.clampV = 0;
textureDef2.samplerState.clampW = 0;
textureDef2.semantic = TS_COLOR_MAP;
textureDef2.isMatureContent = false;
material->constantCount = 2;
material->constantTable = memory.Alloc<MaterialConstantDef>(2);
auto& constantDef0 = material->constantTable[0];
constantDef0.nameHash = 0x3d9994dc;
strncpy(constantDef0.name, "envMapParms", std::extent_v<decltype(MaterialConstantDef::name)>);
constantDef0.literal.x = 1.0f;
constantDef0.literal.y = 1.0f;
constantDef0.literal.z = 1.0f;
constantDef0.literal.w = 0.5f;
auto& constantDef1 = material->constantTable[1];
constantDef1.nameHash = 0xb4de4d82;
strncpy(constantDef1.name, "dynamicFolia", std::extent_v<decltype(MaterialConstantDef::name)>);
constantDef1.literal.x = 0.0f;
constantDef1.literal.y = 1.0f;
constantDef1.literal.z = 0.0f;
constantDef1.literal.w = 1.0f;
material->stateBitsCount = 6;
material->stateBitsTable = memory.Alloc<GfxStateBits>(6);
auto& stateBits0 = material->stateBitsTable[0];
stateBits0.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits0.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits0.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits0.loadBits.structured.alphaTestDisabled = 1;
stateBits0.loadBits.structured.alphaTest = 0;
stateBits0.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits0.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits0.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits0.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits0.loadBits.structured.colorWriteRgb = 0;
stateBits0.loadBits.structured.colorWriteAlpha = 0;
stateBits0.loadBits.structured.polymodeLine = 0;
stateBits0.loadBits.structured.depthWrite = 1;
stateBits0.loadBits.structured.depthTestDisabled = 0;
stateBits0.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits0.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits0.loadBits.structured.stencilFrontEnabled = 1;
stateBits0.loadBits.structured.stencilFrontPass = GFXS_STENCILOP_KEEP;
stateBits0.loadBits.structured.stencilFrontFail = GFXS_STENCILOP_KEEP;
stateBits0.loadBits.structured.stencilFrontZFail = GFXS_STENCILOP_KEEP;
stateBits0.loadBits.structured.stencilFrontFunc = GFXS_STENCILFUNC_EQUAL;
stateBits0.loadBits.structured.stencilBackEnabled = 0;
stateBits0.loadBits.structured.stencilBackPass = 0;
stateBits0.loadBits.structured.stencilBackFail = 0;
stateBits0.loadBits.structured.stencilBackZFail = 0;
stateBits0.loadBits.structured.stencilBackFunc = 0;
auto& stateBits1 = material->stateBitsTable[1];
stateBits1.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits1.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits1.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits1.loadBits.structured.alphaTestDisabled = 1;
stateBits1.loadBits.structured.alphaTest = 0;
stateBits1.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits1.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits1.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits1.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits1.loadBits.structured.colorWriteRgb = 1;
stateBits1.loadBits.structured.colorWriteAlpha = 1;
stateBits1.loadBits.structured.polymodeLine = 0;
stateBits1.loadBits.structured.depthWrite = 1;
stateBits1.loadBits.structured.depthTestDisabled = 0;
stateBits1.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits1.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits1.loadBits.structured.stencilFrontEnabled = 0;
stateBits1.loadBits.structured.stencilFrontPass = 0;
stateBits1.loadBits.structured.stencilFrontFail = 0;
stateBits1.loadBits.structured.stencilFrontZFail = 0;
stateBits1.loadBits.structured.stencilFrontFunc = 0;
stateBits1.loadBits.structured.stencilBackEnabled = 0;
stateBits1.loadBits.structured.stencilBackPass = 0;
stateBits1.loadBits.structured.stencilBackFail = 0;
stateBits1.loadBits.structured.stencilBackZFail = 0;
stateBits1.loadBits.structured.stencilBackFunc = 0;
auto& stateBits2 = material->stateBitsTable[2];
stateBits2.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits2.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits2.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits2.loadBits.structured.alphaTestDisabled = 1;
stateBits2.loadBits.structured.alphaTest = 0;
stateBits2.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits2.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits2.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits2.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits2.loadBits.structured.colorWriteRgb = 0;
stateBits2.loadBits.structured.colorWriteAlpha = 0;
stateBits2.loadBits.structured.polymodeLine = 0;
stateBits2.loadBits.structured.depthWrite = 1;
stateBits2.loadBits.structured.depthTestDisabled = 0;
stateBits2.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits2.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_SHADOWMAP;
stateBits2.loadBits.structured.stencilFrontEnabled = 0;
stateBits2.loadBits.structured.stencilFrontPass = 0;
stateBits2.loadBits.structured.stencilFrontFail = 0;
stateBits2.loadBits.structured.stencilFrontZFail = 0;
stateBits2.loadBits.structured.stencilFrontFunc = 0;
stateBits2.loadBits.structured.stencilBackEnabled = 0;
stateBits2.loadBits.structured.stencilBackPass = 0;
stateBits2.loadBits.structured.stencilBackFail = 0;
stateBits2.loadBits.structured.stencilBackZFail = 0;
stateBits2.loadBits.structured.stencilBackFunc = 0;
auto& stateBits3 = material->stateBitsTable[3];
stateBits3.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits3.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits3.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits3.loadBits.structured.alphaTestDisabled = 1;
stateBits3.loadBits.structured.alphaTest = 0;
stateBits3.loadBits.structured.cullFace = GFXS_CULL_NONE;
stateBits3.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits3.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits3.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits3.loadBits.structured.colorWriteRgb = 1;
stateBits3.loadBits.structured.colorWriteAlpha = 1;
stateBits3.loadBits.structured.polymodeLine = 0;
stateBits3.loadBits.structured.depthWrite = 1;
stateBits3.loadBits.structured.depthTestDisabled = 0;
stateBits3.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits3.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits3.loadBits.structured.stencilFrontEnabled = 0;
stateBits3.loadBits.structured.stencilFrontPass = 0;
stateBits3.loadBits.structured.stencilFrontFail = 0;
stateBits3.loadBits.structured.stencilFrontZFail = 0;
stateBits3.loadBits.structured.stencilFrontFunc = 0;
stateBits3.loadBits.structured.stencilBackEnabled = 0;
stateBits3.loadBits.structured.stencilBackPass = 0;
stateBits3.loadBits.structured.stencilBackFail = 0;
stateBits3.loadBits.structured.stencilBackZFail = 0;
stateBits3.loadBits.structured.stencilBackFunc = 0;
auto& stateBits4 = material->stateBitsTable[4];
stateBits4.loadBits.structured.srcBlendRgb = GFXS_BLEND_INVDESTALPHA;
stateBits4.loadBits.structured.dstBlendRgb = GFXS_BLEND_ONE;
stateBits4.loadBits.structured.blendOpRgb = GFXS_BLENDOP_ADD;
stateBits4.loadBits.structured.alphaTestDisabled = 1;
stateBits4.loadBits.structured.alphaTest = 0;
stateBits4.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits4.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits4.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits4.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits4.loadBits.structured.colorWriteRgb = 1;
stateBits4.loadBits.structured.colorWriteAlpha = 1;
stateBits4.loadBits.structured.polymodeLine = 0;
stateBits4.loadBits.structured.depthWrite = 0;
stateBits4.loadBits.structured.depthTestDisabled = 0;
stateBits4.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits4.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_0;
stateBits4.loadBits.structured.stencilFrontEnabled = 0;
stateBits4.loadBits.structured.stencilFrontPass = 0;
stateBits4.loadBits.structured.stencilFrontFail = 0;
stateBits4.loadBits.structured.stencilFrontZFail = 0;
stateBits4.loadBits.structured.stencilFrontFunc = 0;
stateBits4.loadBits.structured.stencilBackEnabled = 0;
stateBits4.loadBits.structured.stencilBackPass = 0;
stateBits4.loadBits.structured.stencilBackFail = 0;
stateBits4.loadBits.structured.stencilBackZFail = 0;
stateBits4.loadBits.structured.stencilBackFunc = 0;
auto& stateBits5 = material->stateBitsTable[5];
stateBits5.loadBits.structured.srcBlendRgb = GFXS_BLEND_ONE;
stateBits5.loadBits.structured.dstBlendRgb = GFXS_BLEND_ZERO;
stateBits5.loadBits.structured.blendOpRgb = GFXS_BLENDOP_DISABLED;
stateBits5.loadBits.structured.alphaTestDisabled = 1;
stateBits5.loadBits.structured.alphaTest = 0;
stateBits5.loadBits.structured.cullFace = GFXS_CULL_BACK;
stateBits5.loadBits.structured.srcBlendAlpha = GFXS_BLEND_ONE;
stateBits5.loadBits.structured.dstBlendAlpha = GFXS_BLEND_ZERO;
stateBits5.loadBits.structured.blendOpAlpha = GFXS_BLENDOP_DISABLED;
stateBits5.loadBits.structured.colorWriteRgb = 1;
stateBits5.loadBits.structured.colorWriteAlpha = 0;
stateBits5.loadBits.structured.polymodeLine = 1;
stateBits5.loadBits.structured.depthWrite = 0;
stateBits5.loadBits.structured.depthTestDisabled = 0;
stateBits5.loadBits.structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
stateBits5.loadBits.structured.polygonOffset = GFXS_POLYGON_OFFSET_2;
stateBits5.loadBits.structured.stencilFrontEnabled = 0;
stateBits5.loadBits.structured.stencilFrontPass = 0;
stateBits5.loadBits.structured.stencilFrontFail = 0;
stateBits5.loadBits.structured.stencilFrontZFail = 0;
stateBits5.loadBits.structured.stencilFrontFunc = 0;
stateBits5.loadBits.structured.stencilBackEnabled = 0;
stateBits5.loadBits.structured.stencilBackPass = 0;
stateBits5.loadBits.structured.stencilBackFail = 0;
stateBits5.loadBits.structured.stencilBackZFail = 0;
stateBits5.loadBits.structured.stencilBackFunc = 0;
pool.AddAsset(std::make_unique<XAssetInfo<Material>>(ASSET_TYPE_MATERIAL, name, material));
}
TEST_CASE("DumperMaterial(T5): Can dump material", "[t5][material][assetdumper]")
{
std::string expected(R"MATERIAL(
{
"$schema": "http://openassettools.dev/schema/material.v1.json",
"_game": "t5",
"_type": "material",
"_version": 1,
"cameraRegion": "lit",
"constants": [
{
"literal": [
1.0,
1.0,
1.0,
0.5
],
"name": "envMapParms"
},
{
"literal": [
0.0,
1.0,
0.0,
1.0
],
"nameFragment": "dynamicFolia",
"nameHash": 3034467714
}
],
"gameFlags": [
"10",
"CASTS_SHADOW"
],
"layeredSurfaceTypes": 536870914,
"sortKey": 4,
"stateBits": [
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one",
"stencilFront": {
"fail": "keep",
"func": "equal",
"pass": "keep",
"zfail": "keep"
}
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": false,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offsetShadowmap",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "none",
"depthTest": "less_equal",
"depthWrite": true,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "add",
"colorWriteAlpha": true,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "one",
"polygonOffset": "offset0",
"polymodeLine": false,
"srcBlendAlpha": "one",
"srcBlendRgb": "invdestalpha"
},
{
"alphaTest": "disabled",
"blendOpAlpha": "disabled",
"blendOpRgb": "disabled",
"colorWriteAlpha": false,
"colorWriteRgb": true,
"cullFace": "back",
"depthTest": "less_equal",
"depthWrite": false,
"dstBlendAlpha": "zero",
"dstBlendRgb": "zero",
"polygonOffset": "offset2",
"polymodeLine": true,
"srcBlendAlpha": "one",
"srcBlendRgb": "one"
}
],
"stateBitsEntry": [
0,
1,
2,
3,
1,
-1,
-1,
-1,
-1,
-1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
-1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
4,
4,
4,
4,
4,
4,
-1,
-1,
-1,
-1,
5,
-1,
1,
1,
-1
],
"stateFlags": 121,
"surfaceTypeBits": 2,
"techniqueSet": "mc_l_sm_r0c0n0s0",
"textureAtlas": {
"columns": 1,
"rows": 1
},
"textures": [
{
"image": "~$white-rgb&~-rjun_art_brick_~a05e7627",
"isMatureContent": false,
"name": "specularMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "specularMap"
},
{
"image": "jun_art_brick_foundation_n",
"isMatureContent": false,
"name": "normalMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "normalMap"
},
{
"image": "~-gjun_art_brick_foundation_c",
"isMatureContent": false,
"name": "colorMap",
"samplerState": {
"clampU": false,
"clampV": false,
"clampW": false,
"filter": "aniso2x",
"mipMap": "nearest"
},
"semantic": "colorMap"
}
]
})MATERIAL");
Zone zone("MockZone", 0, IGame::GetGameById(GameId::T5));
MemoryManager memory;
MockSearchPath mockObjPath;
MockOutputPath mockOutput;
AssetDumpingContext context(zone, "", mockOutput, mockObjPath);
AssetPoolDynamic<Material> materialPool(0);
GivenMaterial("mc/ch_rubble01", materialPool, memory);
AssetDumperMaterial dumper;
dumper.DumpPool(context, &materialPool);
const auto* file = mockOutput.GetMockedFile("materials/mc/ch_rubble01.json");
REQUIRE(file);
REQUIRE(JsonNormalized(file->AsString()) == JsonNormalized(expected));
}
} // namespace

View File

@@ -261,6 +261,7 @@ namespace
{ {
std::string expected(R"MATERIAL( std::string expected(R"MATERIAL(
{ {
"$schema": "http://openassettools.dev/schema/material.v1.json",
"_game": "t6", "_game": "t6",
"_type": "material", "_type": "material",
"_version": 1, "_version": 1,
@@ -282,9 +283,7 @@ namespace
"10", "10",
"CASTS_SHADOW" "CASTS_SHADOW"
], ],
"hashIndex": 0,
"layeredSurfaceTypes": 536870925, "layeredSurfaceTypes": 536870925,
"probeMipBits": 0,
"sortKey": 4, "sortKey": 4,
"stateBits": [ "stateBits": [
{ {