mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-07-04 02:01:51 +00:00
feat: add json material loading/writing for iw3
This commit is contained in:
@ -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]);
|
||||||
|
@ -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
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#options GAME (IW4, IW5, T6)
|
#options GAME (IW3, IW4, IW5, 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"
|
||||||
@ -75,7 +78,7 @@ 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,
|
||||||
#endif
|
#endif
|
||||||
GE128
|
GE128
|
||||||
@ -85,7 +88,7 @@ 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" },
|
||||||
#endif
|
#endif
|
||||||
{JsonAlphaTest::GE128, "ge128" }
|
{JsonAlphaTest::GE128, "ge128" }
|
||||||
@ -315,34 +318,28 @@ 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_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" },
|
||||||
|
#if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
||||||
{TS_UNUSED_6, "unused6" },
|
{TS_UNUSED_6, "unused6" },
|
||||||
{TS_WATER_MAP, "waterMap" },
|
{TS_WATER_MAP, "waterMap" },
|
||||||
#ifdef FEATURE_IW5
|
#ifdef FEATURE_IW5
|
||||||
{TS_DISPLACEMENT_MAP, "displacementMap"},
|
{TS_DISPLACEMENT_MAP, "displacementMap"},
|
||||||
#endif
|
#endif
|
||||||
#elif defined(FEATURE_T6)
|
#elif defined(FEATURE_T6)
|
||||||
{TS_2D, "2D" },
|
{TS_OCCLUSION_MAP, "occlusionMap" },
|
||||||
{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_UNUSED_6, "unused6" },
|
||||||
{TS_COLOR0_MAP, "color0Map" },
|
{TS_COLOR0_MAP, "color0Map" },
|
||||||
{TS_COLOR1_MAP, "color1Map" },
|
{TS_COLOR1_MAP, "color1Map" },
|
||||||
@ -437,26 +434,25 @@ 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_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" },
|
||||||
|
#ifdef FEATURE_T6
|
||||||
{MTL_GAMEFLAG_100, "100" },
|
{MTL_GAMEFLAG_100, "100" },
|
||||||
{MTL_GAMEFLAG_200, "200" },
|
{MTL_GAMEFLAG_200, "200" },
|
||||||
{MTL_GAMEFLAG_400, "400" },
|
{MTL_GAMEFLAG_400, "400" },
|
||||||
@ -466,7 +462,11 @@ namespace GAME
|
|||||||
});
|
});
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(GfxCameraRegionType, {
|
NLOHMANN_JSON_SERIALIZE_ENUM(GfxCameraRegionType, {
|
||||||
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
#if defined(FEATURE_IW3)
|
||||||
|
{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 +474,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,8 +485,8 @@ 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
|
||||||
|
54
src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.cpp
Normal file
54
src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.cpp
Normal 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
|
12
src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.h
Normal file
12
src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.h
Normal 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
|
@ -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));
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
#options GAME (IW4, IW5, T6)
|
#options GAME (IW3, IW4, IW5, 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"
|
||||||
@ -94,7 +98,7 @@ 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_T6)
|
||||||
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags)
|
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags)
|
||||||
@ -304,7 +308,7 @@ 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;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#options GAME (IW4, IW5, T6)
|
#options GAME (IW3, IW4, IW5, T6)
|
||||||
|
|
||||||
#filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".h"
|
#filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".h"
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
30
src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.cpp
Normal file
30
src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.cpp
Normal 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);
|
||||||
|
}
|
@ -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;
|
@ -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
|
@ -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
|
@ -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;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IObjWriter.h"
|
#include "IObjWriter.h"
|
||||||
|
|
||||||
namespace IW3
|
namespace IW3
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
#options GAME (IW4, IW5, T6)
|
#options GAME (IW3, IW4, IW5, 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"
|
||||||
@ -218,7 +222,7 @@ 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
|
||||||
#endif
|
#endif
|
||||||
|| structured.alphaTest == GFXS_ALPHA_TEST_GE_128);
|
|| structured.alphaTest == GFXS_ALPHA_TEST_GE_128);
|
||||||
@ -226,7 +230,7 @@ namespace
|
|||||||
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;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#options GAME (IW4, IW5, T6)
|
#options GAME (IW3, IW4, IW5, T6)
|
||||||
|
|
||||||
#filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".h"
|
#filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".h"
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
577
test/ObjLoadingTests/Game/IW3/Material/LoaderMaterialIW3Test.cpp
Normal file
577
test/ObjLoadingTests/Game/IW3/Material/LoaderMaterialIW3Test.cpp
Normal 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
|
571
test/ObjWritingTests/Game/IW3/Material/DumperMaterialIW3Test.cpp
Normal file
571
test/ObjWritingTests/Game/IW3/Material/DumperMaterialIW3Test.cpp
Normal file
@ -0,0 +1,571 @@
|
|||||||
|
#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(
|
||||||
|
{
|
||||||
|
"_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
|
Reference in New Issue
Block a user