From 116f008f90a336b077a15b6ab6719037d922de4b Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 28 Jun 2025 23:24:12 +0100 Subject: [PATCH] chore: add tests for material loading for iw4,iw5,t6 --- .../IW4/Material/LoaderMaterialIW4Test.cpp | 558 ++++++++++++++++ .../IW5/Material/LoaderMaterialIW5Test.cpp | 611 ++++++++++++++++++ .../Game/T6/Material/LoaderMaterialT6Test.cpp | 491 ++++++++++++++ 3 files changed, 1660 insertions(+) create mode 100644 test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp create mode 100644 test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp create mode 100644 test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp diff --git a/test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp b/test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp new file mode 100644 index 00000000..0860550b --- /dev/null +++ b/test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp @@ -0,0 +1,558 @@ +#include "Game/IW4/Material/LoaderMaterialIW4.h" + +#include "Game/IW4/CommonIW4.h" +#include "Game/IW4/GameIW4.h" +#include "SearchPath/MockSearchPath.h" +#include "Utils/MemoryManager.h" + +#include +#include +#include + +using namespace IW4; +using namespace Catch; +using namespace std::literals; + +namespace +{ + void GivenImage(const std::string& name, AssetCreationContext& context, MemoryManager& memory) + { + auto* image = memory.Alloc(); + image->name = memory.Dup(name.c_str()); + + AssetRegistration registration(name); + registration.SetAsset(image); + context.AddAsset(std::move(registration)); + } + + void GivenTechset(const std::string& name, AssetCreationContext& context, MemoryManager& memory) + { + auto* techset = memory.Alloc(); + techset->name = memory.Dup(name.c_str()); + + AssetRegistration registration(name); + registration.SetAsset(techset); + context.AddAsset(std::move(registration)); + } + + TEST_CASE("LoaderMaterial(IW4): Can parse material", "[iw4][material][assetloader]") + { + MockSearchPath searchPath; + searchPath.AddFileData("materials/mc/ch_rubble01.json", + R"MATERIAL( +{ + "_game": "iw4", + "_type": "material", + "_version": 1, + "cameraRegion": "litOpaque", + "constants": [ + { + "literal": [ + 0.07000000029802322, + 0.46000000834465027, + 1.600000023841858, + 2.0 + ], + "name": "envMapParms" + }, + { + "literal": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "name": "colorTint" + } + ], + "gameFlags": [ + "10", + "40" + ], + "sortKey": 1, + "stateBits": [ + { + "alphaTest": "disabled", + "blendOpAlpha": "disabled", + "blendOpRgb": "disabled", + "colorWriteAlpha": false, + "colorWriteRgb": false, + "cullFace": "back", + "depthTest": "less_equal", + "depthWrite": true, + "dstBlendAlpha": "zero", + "dstBlendRgb": "zero", + "gammaWrite": false, + "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", + "gammaWrite": false, + "polygonOffset": "offset0", + "polymodeLine": false, + "srcBlendAlpha": "one", + "srcBlendRgb": "one" + }, + { + "alphaTest": "disabled", + "blendOpAlpha": "disabled", + "blendOpRgb": "disabled", + "colorWriteAlpha": false, + "colorWriteRgb": false, + "cullFace": "back", + "depthTest": "less_equal", + "depthWrite": true, + "dstBlendAlpha": "zero", + "dstBlendRgb": "zero", + "gammaWrite": false, + "polygonOffset": "offsetShadowmap", + "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", + "gammaWrite": true, + "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", + "gammaWrite": true, + "polygonOffset": "offset0", + "polymodeLine": false, + "srcBlendAlpha": "one", + "srcBlendRgb": "one", + "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", + "gammaWrite": false, + "polygonOffset": "offset2", + "polymodeLine": true, + "srcBlendAlpha": "one", + "srcBlendRgb": "one" + } + ], + "stateBitsEntry": [ + 0, + 1, + 2, + 1, + 3, + -1, + -1, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 4, + 4, + 4, + -1, + -1, + -1, + -1, + 5, + -1, + 3, + 3 + ], + "stateFlags": 121, + "surfaceTypeBits": 16, + "techniqueSet": "mc_l_sm_r0c0n0s0", + "textureAtlas": { + "columns": 1, + "rows": 1 + }, + "textures": [ + { + "image": "~ch_rubble02_spc-r-74g-74b-74~1eb1f0d0", + "name": "specularMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso2x", + "mipMap": "nearest" + }, + "semantic": "specularMap" + }, + { + "image": "ch_rubble01_nml", + "name": "normalMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso2x", + "mipMap": "nearest" + }, + "semantic": "normalMap" + }, + { + "image": "ch_rubble01_col", + "name": "colorMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso2x", + "mipMap": "nearest" + }, + "semantic": "colorMap" + } + ] +})MATERIAL"); + + Zone zone("MockZone", 0, IGame::GetGameById(GameId::IW4)); + + MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); + + GivenImage("~ch_rubble02_spc-r-74g-74b-74~1eb1f0d0", context, memory); + GivenImage("ch_rubble01_nml", context, memory); + GivenImage("ch_rubble01_col", context, memory); + GivenTechset("mc_l_sm_r0c0n0s0", context, memory); + + auto loader = CreateMaterialLoader(memory, searchPath); + auto result = loader->CreateAsset("mc/ch_rubble01", context); + REQUIRE(result.HasBeenSuccessful()); + + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); + const auto* material = assetInfo->Asset(); + + REQUIRE(material->info.name == "mc/ch_rubble01"s); + REQUIRE(material->info.gameFlags == 0x50); + REQUIRE(material->info.sortKey == 1); + REQUIRE(material->info.textureAtlasRowCount == 1); + REQUIRE(material->info.textureAtlasColumnCount == 1); + REQUIRE(material->info.surfaceTypeBits == 16); + + constexpr int8_t expectedStateBitsEntry[]{0, 1, 2, 1, 3, -1, -1, -1, -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, -1, -1, -1, -1, 5, -1, 3, 3}; + REQUIRE(std::memcmp(material->stateBitsEntry, expectedStateBitsEntry, sizeof(expectedStateBitsEntry)) == 0); + + REQUIRE(material->stateFlags == 121); + REQUIRE(material->cameraRegion == CAMERA_REGION_LIT_OPAQUE); + + REQUIRE(material->techniqueSet != nullptr); + REQUIRE(material->techniqueSet->name != nullptr); + REQUIRE(material->techniqueSet->name == "mc_l_sm_r0c0n0s0"s); + + REQUIRE(material->textureCount == 3); + REQUIRE(material->textureTable); + + const auto& textureDef0 = material->textureTable[0]; + REQUIRE(textureDef0.nameHash == 0x34ecccb3); + REQUIRE(textureDef0.nameStart == 's'); + REQUIRE(textureDef0.nameEnd == 'p'); + REQUIRE(textureDef0.samplerState.filter == TEXTURE_FILTER_ANISO2X); + REQUIRE(textureDef0.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_NEAREST); + REQUIRE(textureDef0.samplerState.clampU == 0); + REQUIRE(textureDef0.samplerState.clampV == 0); + REQUIRE(textureDef0.samplerState.clampW == 0); + REQUIRE(textureDef0.semantic == TS_SPECULAR_MAP); + REQUIRE(textureDef0.u.image); + REQUIRE(textureDef0.u.image->name); + REQUIRE(textureDef0.u.image->name == "~ch_rubble02_spc-r-74g-74b-74~1eb1f0d0"s); + + const auto& textureDef1 = material->textureTable[1]; + REQUIRE(textureDef1.nameHash == 0x59d30d0f); + REQUIRE(textureDef1.nameStart == 'n'); + REQUIRE(textureDef1.nameEnd == 'p'); + REQUIRE(textureDef1.samplerState.filter == TEXTURE_FILTER_ANISO2X); + REQUIRE(textureDef1.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_NEAREST); + REQUIRE(textureDef1.samplerState.clampU == 0); + REQUIRE(textureDef1.samplerState.clampV == 0); + REQUIRE(textureDef1.samplerState.clampW == 0); + REQUIRE(textureDef1.semantic == TS_NORMAL_MAP); + REQUIRE(textureDef1.u.image); + REQUIRE(textureDef1.u.image->name); + REQUIRE(textureDef1.u.image->name == "ch_rubble01_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_NEAREST); + 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_rubble01_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) == 0); + REQUIRE(constantDef0.literal.x == Approx(0.07f)); + REQUIRE(constantDef0.literal.y == Approx(0.46f)); + REQUIRE(constantDef0.literal.z == Approx(1.6f)); + REQUIRE(constantDef0.literal.w == Approx(2.0f)); + + const auto& constantDef1 = material->constantTable[1]; + REQUIRE(constantDef1.nameHash == 0xb60c3b3a); + REQUIRE(strncmp(constantDef1.name, "colorTint", std::extent_v) == 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 == 6); + REQUIRE(material->stateBitsTable); + + const auto& stateBits0 = material->stateBitsTable[0]; + REQUIRE(stateBits0.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE); + REQUIRE(stateBits0.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO); + REQUIRE(stateBits0.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits0.loadBits.structured.alphaTestDisabled == 1); + REQUIRE(stateBits0.loadBits.structured.alphaTest == 0); + REQUIRE(stateBits0.loadBits.structured.cullFace == GFXS_CULL_BACK); + REQUIRE(stateBits0.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE); + REQUIRE(stateBits0.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO); + REQUIRE(stateBits0.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits0.loadBits.structured.colorWriteRgb == 0); + REQUIRE(stateBits0.loadBits.structured.colorWriteAlpha == 0); + REQUIRE(stateBits0.loadBits.structured.gammaWrite == 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.gammaWrite == 0); + REQUIRE(stateBits1.loadBits.structured.polymodeLine == 0); + REQUIRE(stateBits1.loadBits.structured.depthWrite == 1); + REQUIRE(stateBits1.loadBits.structured.depthTestDisabled == 0); + REQUIRE(stateBits1.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL); + REQUIRE(stateBits1.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontEnabled == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontPass == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontZFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontFunc == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackEnabled == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackPass == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackZFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackFunc == 0); + + const auto& stateBits2 = material->stateBitsTable[2]; + REQUIRE(stateBits2.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE); + REQUIRE(stateBits2.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO); + REQUIRE(stateBits2.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits2.loadBits.structured.alphaTestDisabled == 1); + REQUIRE(stateBits2.loadBits.structured.alphaTest == 0); + REQUIRE(stateBits2.loadBits.structured.cullFace == GFXS_CULL_BACK); + REQUIRE(stateBits2.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE); + REQUIRE(stateBits2.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO); + REQUIRE(stateBits2.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits2.loadBits.structured.colorWriteRgb == 0); + REQUIRE(stateBits2.loadBits.structured.colorWriteAlpha == 0); + REQUIRE(stateBits2.loadBits.structured.gammaWrite == 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_BACK); + 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.gammaWrite == 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_ONE); + 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.gammaWrite == 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.gammaWrite == 0); + REQUIRE(stateBits5.loadBits.structured.polymodeLine == 1); + REQUIRE(stateBits5.loadBits.structured.depthWrite == 0); + REQUIRE(stateBits5.loadBits.structured.depthTestDisabled == 0); + REQUIRE(stateBits5.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL); + REQUIRE(stateBits5.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_2); + REQUIRE(stateBits5.loadBits.structured.stencilFrontEnabled == 0); + REQUIRE(stateBits5.loadBits.structured.stencilFrontPass == 0); + REQUIRE(stateBits5.loadBits.structured.stencilFrontFail == 0); + REQUIRE(stateBits5.loadBits.structured.stencilFrontZFail == 0); + REQUIRE(stateBits5.loadBits.structured.stencilFrontFunc == 0); + REQUIRE(stateBits5.loadBits.structured.stencilBackEnabled == 0); + REQUIRE(stateBits5.loadBits.structured.stencilBackPass == 0); + REQUIRE(stateBits5.loadBits.structured.stencilBackFail == 0); + REQUIRE(stateBits5.loadBits.structured.stencilBackZFail == 0); + REQUIRE(stateBits5.loadBits.structured.stencilBackFunc == 0); + } +} // namespace diff --git a/test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp b/test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp new file mode 100644 index 00000000..5de6912b --- /dev/null +++ b/test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp @@ -0,0 +1,611 @@ +#include "Game/IW5/Material/LoaderMaterialIW5.h" + +#include "Game/IW5/CommonIW5.h" +#include "Game/IW5/GameIW5.h" +#include "SearchPath/MockSearchPath.h" +#include "Utils/MemoryManager.h" + +#include +#include +#include + +using namespace IW5; +using namespace Catch; +using namespace std::literals; + +namespace +{ + void GivenImage(const std::string& name, AssetCreationContext& context, MemoryManager& memory) + { + auto* image = memory.Alloc(); + image->name = memory.Dup(name.c_str()); + + AssetRegistration registration(name); + registration.SetAsset(image); + context.AddAsset(std::move(registration)); + } + + void GivenTechset(const std::string& name, AssetCreationContext& context, MemoryManager& memory) + { + auto* techset = memory.Alloc(); + techset->name = memory.Dup(name.c_str()); + + AssetRegistration registration(name); + registration.SetAsset(techset); + context.AddAsset(std::move(registration)); + } + + TEST_CASE("LoaderMaterial(IW5): Can parse material", "[iw5][material][assetloader]") + { + MockSearchPath searchPath; + searchPath.AddFileData("materials/wc/me_metal_rust_02.json", + R"MATERIAL( +{ + "_game": "iw5", + "_type": "material", + "_version": 1, + "cameraRegion": "litOpaque", + "constants": [ + { + "literal": [ + 0.07000000029802322, + 0.33000001311302185, + 1.399999976158142, + 2.0 + ], + "name": "envMapParms" + }, + { + "literal": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "name": "colorTint" + } + ], + "gameFlags": [ + "2", + "10", + "40" + ], + "sortKey": 1, + "stateBits": [ + { + "alphaTest": "disabled", + "blendOpAlpha": "disabled", + "blendOpRgb": "disabled", + "colorWriteAlpha": false, + "colorWriteRgb": false, + "cullFace": "back", + "depthTest": "less_equal", + "depthWrite": true, + "dstBlendAlpha": "zero", + "dstBlendRgb": "zero", + "gammaWrite": false, + "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", + "gammaWrite": false, + "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", + "gammaWrite": false, + "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", + "gammaWrite": false, + "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", + "gammaWrite": true, + "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", + "gammaWrite": true, + "polygonOffset": "offset0", + "polymodeLine": false, + "srcBlendAlpha": "one", + "srcBlendRgb": "one", + "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", + "gammaWrite": false, + "polygonOffset": "offset2", + "polymodeLine": true, + "srcBlendAlpha": "one", + "srcBlendRgb": "one" + } + ], + "stateBitsEntry": [ + 0, + 1, + 2, + 3, + 4, + -1, + -1, + -1, + -1, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + 5, + 5, + 5, + 5, + -1, + -1, + -1, + -1, + 6, + -1, + -1, + 4, + -1 + ], + "stateFlags": 59, + "surfaceTypeBits": 4096, + "techniqueSet": "wc_l_sm_r0c0n0s0", + "textureAtlas": { + "columns": 1, + "rows": 1 + }, + "textures": [ + { + "image": "~me_metal_rusty02_spc-rgb&me_~927de80f", + "name": "specularMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso2x", + "mipMap": "nearest" + }, + "semantic": "specularMap" + }, + { + "image": "me_metal_rusty02_nml", + "name": "normalMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso2x", + "mipMap": "linear" + }, + "semantic": "normalMap" + }, + { + "image": "me_metal_rusty02_col", + "name": "colorMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso2x", + "mipMap": "linear" + }, + "semantic": "colorMap" + } + ] +})MATERIAL"); + + Zone zone("MockZone", 0, IGame::GetGameById(GameId::IW5)); + + MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); + + GivenImage("~me_metal_rusty02_spc-rgb&me_~927de80f", context, memory); + GivenImage("me_metal_rusty02_nml", context, memory); + GivenImage("me_metal_rusty02_col", context, memory); + GivenTechset("wc_l_sm_r0c0n0s0", context, memory); + + auto loader = CreateMaterialLoader(memory, searchPath); + auto result = loader->CreateAsset("wc/me_metal_rust_02", context); + REQUIRE(result.HasBeenSuccessful()); + + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); + const auto* material = assetInfo->Asset(); + + REQUIRE(material->info.name == "wc/me_metal_rust_02"s); + REQUIRE(material->info.gameFlags == 0x52); + REQUIRE(material->info.sortKey == 1); + REQUIRE(material->info.textureAtlasRowCount == 1); + REQUIRE(material->info.textureAtlasColumnCount == 1); + REQUIRE(material->info.surfaceTypeBits == 4096); + + constexpr int8_t expectedStateBitsEntry[]{0, 1, 2, 3, 4, -1, -1, -1, -1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, 5, 5, -1, -1, -1, -1, 6, -1, -1, 4, -1}; + REQUIRE(std::memcmp(material->stateBitsEntry, expectedStateBitsEntry, sizeof(expectedStateBitsEntry)) == 0); + + REQUIRE(material->stateFlags == 59); + REQUIRE(material->cameraRegion == CAMERA_REGION_LIT_OPAQUE); + + 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 == "~me_metal_rusty02_spc-rgb&me_~927de80f"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 == "me_metal_rusty02_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 == "me_metal_rusty02_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) == 0); + REQUIRE(constantDef0.literal.x == Approx(0.07f)); + REQUIRE(constantDef0.literal.y == Approx(0.33f)); + REQUIRE(constantDef0.literal.z == Approx(1.4f)); + REQUIRE(constantDef0.literal.w == Approx(2.0f)); + + const auto& constantDef1 = material->constantTable[1]; + REQUIRE(constantDef1.nameHash == 0xb60c3b3a); + REQUIRE(strncmp(constantDef1.name, "colorTint", std::extent_v) == 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.gammaWrite == 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.gammaWrite == 0); + 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.gammaWrite == 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.gammaWrite == 0); + 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_ONE); + REQUIRE(stateBits4.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO); + REQUIRE(stateBits4.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED); + 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.gammaWrite == 1); + REQUIRE(stateBits4.loadBits.structured.polymodeLine == 0); + REQUIRE(stateBits4.loadBits.structured.depthWrite == 1); + REQUIRE(stateBits4.loadBits.structured.depthTestDisabled == 0); + REQUIRE(stateBits4.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL); + REQUIRE(stateBits4.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontEnabled == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontPass == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontZFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontFunc == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackEnabled == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackPass == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackZFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackFunc == 0); + + const auto& stateBits5 = material->stateBitsTable[5]; + REQUIRE(stateBits5.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE); + REQUIRE(stateBits5.loadBits.structured.dstBlendRgb == GFXS_BLEND_ONE); + REQUIRE(stateBits5.loadBits.structured.blendOpRgb == GFXS_BLENDOP_ADD); + 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 == 1); + REQUIRE(stateBits5.loadBits.structured.gammaWrite == 1); + REQUIRE(stateBits5.loadBits.structured.polymodeLine == 0); + REQUIRE(stateBits5.loadBits.structured.depthWrite == 0); + REQUIRE(stateBits5.loadBits.structured.depthTestDisabled == 0); + REQUIRE(stateBits5.loadBits.structured.depthTest == GFXS_DEPTHTEST_EQUAL); + REQUIRE(stateBits5.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0); + REQUIRE(stateBits5.loadBits.structured.stencilFrontEnabled == 1); + REQUIRE(stateBits5.loadBits.structured.stencilFrontPass == GFXS_STENCILOP_KEEP); + REQUIRE(stateBits5.loadBits.structured.stencilFrontFail == GFXS_STENCILOP_KEEP); + REQUIRE(stateBits5.loadBits.structured.stencilFrontZFail == GFXS_STENCILOP_KEEP); + REQUIRE(stateBits5.loadBits.structured.stencilFrontFunc == GFXS_STENCILFUNC_EQUAL); + 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_ONE); + REQUIRE(stateBits6.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO); + REQUIRE(stateBits6.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED); + 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 == 0); + REQUIRE(stateBits6.loadBits.structured.gammaWrite == 0); + REQUIRE(stateBits6.loadBits.structured.polymodeLine == 1); + 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 diff --git a/test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp b/test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp new file mode 100644 index 00000000..2596dc78 --- /dev/null +++ b/test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp @@ -0,0 +1,491 @@ +#include "Game/T6/Material/LoaderMaterialT6.h" + +#include "Game/T6/CommonT6.h" +#include "Game/T6/GameT6.h" +#include "SearchPath/MockSearchPath.h" +#include "Utils/MemoryManager.h" + +#include +#include +#include + +using namespace T6; +using namespace Catch; +using namespace std::literals; + +namespace +{ + void GivenImage(const std::string& name, AssetCreationContext& context, MemoryManager& memory) + { + auto* image = memory.Alloc(); + image->name = memory.Dup(name.c_str()); + + AssetRegistration registration(name); + registration.SetAsset(image); + context.AddAsset(std::move(registration)); + } + + void GivenTechset(const std::string& name, AssetCreationContext& context, MemoryManager& memory) + { + auto* techset = memory.Alloc(); + techset->name = memory.Dup(name.c_str()); + + AssetRegistration registration(name); + registration.SetAsset(techset); + context.AddAsset(std::move(registration)); + } + + TEST_CASE("LoaderMaterial(T6): Can parse material", "[t6][material][assetloader]") + { + MockSearchPath searchPath; + searchPath.AddFileData("materials/wpc/metal_ac_duct.json", + R"MATERIAL( +{ + "_game": "t6", + "_type": "material", + "_version": 1, + "cameraRegion": "litOpaque", + "constants": [ + { + "literal": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "name": "occlusionAmount" + } + ], + "contents": 1, + "gameFlags": [ + "2", + "10", + "CASTS_SHADOW" + ], + "hashIndex": 0, + "layeredSurfaceTypes": 536870925, + "probeMipBits": 0, + "sortKey": 4, + "stateBits": [ + { + "alphaTest": "disabled", + "blendOpAlpha": "disabled", + "blendOpRgb": "disabled", + "colorWriteAlpha": false, + "colorWriteRgb": false, + "cullFace": "back", + "depthTest": "less_equal", + "depthWrite": true, + "dstBlendAlpha": "zero", + "dstBlendRgb": "zero", + "polygonOffset": "offset0", + "polymodeLine": false, + "srcBlendAlpha": "one", + "srcBlendRgb": "one", + "stencilFront": { + "fail": "keep", + "func": "equal", + "pass": "keep", + "zfail": "keep" + } + }, + { + "alphaTest": "disabled", + "blendOpAlpha": "disabled", + "blendOpRgb": "disabled", + "colorWriteAlpha": false, + "colorWriteRgb": false, + "cullFace": "back", + "depthTest": "less_equal", + "depthWrite": true, + "dstBlendAlpha": "zero", + "dstBlendRgb": "zero", + "polygonOffset": "offsetShadowmap", + "polymodeLine": false, + "srcBlendAlpha": "one", + "srcBlendRgb": "one" + }, + { + "alphaTest": "disabled", + "blendOpAlpha": "disabled", + "blendOpRgb": "disabled", + "colorWriteAlpha": true, + "colorWriteRgb": true, + "cullFace": "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": 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": true, + "dstBlendAlpha": "zero", + "dstBlendRgb": "one", + "polygonOffset": "offset1", + "polymodeLine": false, + "srcBlendAlpha": "one", + "srcBlendRgb": "one" + } + ], + "stateBitsEntry": [ + 0, + 1, + 2, + -1, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + -1, + -1, + -1, + -1, + 3, + -1, + 2, + 4 + ], + "stateFlags": 121, + "surfaceFlags": 13631488, + "surfaceTypeBits": 4096, + "techniqueSet": "wpc_lit_sm_r0c0n0s0_1zzj1138", + "textureAtlas": { + "columns": 1, + "rows": 1 + }, + "textures": [ + { + "image": "~~-gmetal_ac_duct_s-rgb&~-rme~0a5a2e6f", + "isMatureContent": false, + "name": "specularMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso4x", + "mipMap": "linear" + }, + "semantic": "specularMap" + }, + { + "image": "metal_ac_duct_n", + "isMatureContent": false, + "name": "normalMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso4x", + "mipMap": "linear" + }, + "semantic": "normalMap" + }, + { + "image": "~-gmetal_ac_duct_c", + "isMatureContent": false, + "name": "colorMap", + "samplerState": { + "clampU": false, + "clampV": false, + "clampW": false, + "filter": "aniso4x", + "mipMap": "linear" + }, + "semantic": "colorMap" + } + ] +})MATERIAL"); + + Zone zone("MockZone", 0, IGame::GetGameById(GameId::T6)); + + MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); + + GivenImage("~~-gmetal_ac_duct_s-rgb&~-rme~0a5a2e6f", context, memory); + GivenImage("metal_ac_duct_n", context, memory); + GivenImage("~-gmetal_ac_duct_c", context, memory); + GivenTechset("wpc_lit_sm_r0c0n0s0_1zzj1138", context, memory); + + auto loader = CreateMaterialLoader(memory, searchPath); + auto result = loader->CreateAsset("wpc/metal_ac_duct", context); + REQUIRE(result.HasBeenSuccessful()); + + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); + const auto* material = assetInfo->Asset(); + + REQUIRE(material->info.name == "wpc/metal_ac_duct"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 == 4096); + REQUIRE(material->info.layeredSurfaceTypes == 0x2000000Du); + REQUIRE(material->info.surfaceFlags == 0xD00000u); + REQUIRE(material->info.contents == 1); + + constexpr int8_t expectedStateBitsEntry[]{0, 1, 2, -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, 3, -1, 2, 4}; + REQUIRE(std::memcmp(material->stateBitsEntry, expectedStateBitsEntry, sizeof(expectedStateBitsEntry)) == 0); + + REQUIRE(material->stateFlags == 121); + REQUIRE(material->cameraRegion == CAMERA_REGION_LIT_OPAQUE); + REQUIRE(material->probeMipBits == 0); + + REQUIRE(material->techniqueSet != nullptr); + REQUIRE(material->techniqueSet->name != nullptr); + REQUIRE(material->techniqueSet->name == "wpc_lit_sm_r0c0n0s0_1zzj1138"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_ANISO4X); + REQUIRE(textureDef0.samplerState.mipMap == SAMPLER_MIPMAP_ENUM_LINEAR); + REQUIRE(textureDef0.samplerState.clampU == 0); + REQUIRE(textureDef0.samplerState.clampV == 0); + REQUIRE(textureDef0.samplerState.clampW == 0); + REQUIRE(textureDef0.semantic == TS_SPECULAR_MAP); + REQUIRE(textureDef0.isMatureContent == false); + REQUIRE(textureDef0.image); + REQUIRE(textureDef0.image->name); + REQUIRE(textureDef0.image->name == "~~-gmetal_ac_duct_s-rgb&~-rme~0a5a2e6f"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_ANISO4X); + 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.isMatureContent == false); + REQUIRE(textureDef1.image); + REQUIRE(textureDef1.image->name); + REQUIRE(textureDef1.image->name == "metal_ac_duct_n"s); + + const auto& textureDef2 = material->textureTable[2]; + REQUIRE(textureDef2.nameHash == 0xa0ab1041); + REQUIRE(textureDef2.nameStart == 'c'); + REQUIRE(textureDef2.nameEnd == 'p'); + REQUIRE(textureDef2.samplerState.filter == TEXTURE_FILTER_ANISO4X); + 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.isMatureContent == false); + REQUIRE(textureDef2.image); + REQUIRE(textureDef2.image->name); + REQUIRE(textureDef2.image->name == "~-gmetal_ac_duct_c"s); + + REQUIRE(material->constantCount == 1); + REQUIRE(material->constantTable); + + const auto& constantDef0 = material->constantTable[0]; + REQUIRE(constantDef0.nameHash == 0x9027e5c1); + REQUIRE(strncmp(constantDef0.name, "occlusionAmount", std::extent_v) == 0); + REQUIRE(constantDef0.literal.x == Approx(1.0f)); + REQUIRE(constantDef0.literal.y == Approx(1.0f)); + REQUIRE(constantDef0.literal.z == Approx(1.0f)); + REQUIRE(constantDef0.literal.w == Approx(1.0f)); + + REQUIRE(material->stateBitsCount == 5); + REQUIRE(material->stateBitsTable); + + const auto& stateBits0 = material->stateBitsTable[0]; + REQUIRE(stateBits0.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE); + REQUIRE(stateBits0.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO); + REQUIRE(stateBits0.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits0.loadBits.structured.alphaTestDisabled == 1); + REQUIRE(stateBits0.loadBits.structured.alphaTest == 0); + REQUIRE(stateBits0.loadBits.structured.cullFace == GFXS_CULL_BACK); + REQUIRE(stateBits0.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE); + REQUIRE(stateBits0.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO); + REQUIRE(stateBits0.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits0.loadBits.structured.colorWriteRgb == 0); + REQUIRE(stateBits0.loadBits.structured.colorWriteAlpha == 0); + REQUIRE(stateBits0.loadBits.structured.polymodeLine == 0); + REQUIRE(stateBits0.loadBits.structured.depthWrite == 1); + REQUIRE(stateBits0.loadBits.structured.depthTestDisabled == 0); + REQUIRE(stateBits0.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL); + REQUIRE(stateBits0.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_0); + REQUIRE(stateBits0.loadBits.structured.stencilFrontEnabled == 1); + REQUIRE(stateBits0.loadBits.structured.stencilFrontPass == GFXS_STENCILOP_KEEP); + REQUIRE(stateBits0.loadBits.structured.stencilFrontFail == GFXS_STENCILOP_KEEP); + REQUIRE(stateBits0.loadBits.structured.stencilFrontZFail == GFXS_STENCILOP_KEEP); + REQUIRE(stateBits0.loadBits.structured.stencilFrontFunc == GFXS_STENCILFUNC_EQUAL); + REQUIRE(stateBits0.loadBits.structured.stencilBackEnabled == 0); + REQUIRE(stateBits0.loadBits.structured.stencilBackPass == 0); + REQUIRE(stateBits0.loadBits.structured.stencilBackFail == 0); + REQUIRE(stateBits0.loadBits.structured.stencilBackZFail == 0); + REQUIRE(stateBits0.loadBits.structured.stencilBackFunc == 0); + + const auto& stateBits1 = material->stateBitsTable[1]; + REQUIRE(stateBits1.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE); + REQUIRE(stateBits1.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO); + REQUIRE(stateBits1.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits1.loadBits.structured.alphaTestDisabled == 1); + REQUIRE(stateBits1.loadBits.structured.alphaTest == 0); + REQUIRE(stateBits1.loadBits.structured.cullFace == GFXS_CULL_BACK); + REQUIRE(stateBits1.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE); + REQUIRE(stateBits1.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO); + REQUIRE(stateBits1.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits1.loadBits.structured.colorWriteRgb == 0); + REQUIRE(stateBits1.loadBits.structured.colorWriteAlpha == 0); + 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_SHADOWMAP); + REQUIRE(stateBits1.loadBits.structured.stencilFrontEnabled == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontPass == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontZFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilFrontFunc == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackEnabled == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackPass == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackZFail == 0); + REQUIRE(stateBits1.loadBits.structured.stencilBackFunc == 0); + + const auto& stateBits2 = material->stateBitsTable[2]; + REQUIRE(stateBits2.loadBits.structured.srcBlendRgb == GFXS_BLEND_ONE); + REQUIRE(stateBits2.loadBits.structured.dstBlendRgb == GFXS_BLEND_ZERO); + REQUIRE(stateBits2.loadBits.structured.blendOpRgb == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits2.loadBits.structured.alphaTestDisabled == 1); + REQUIRE(stateBits2.loadBits.structured.alphaTest == 0); + REQUIRE(stateBits2.loadBits.structured.cullFace == GFXS_CULL_BACK); + REQUIRE(stateBits2.loadBits.structured.srcBlendAlpha == GFXS_BLEND_ONE); + REQUIRE(stateBits2.loadBits.structured.dstBlendAlpha == GFXS_BLEND_ZERO); + REQUIRE(stateBits2.loadBits.structured.blendOpAlpha == GFXS_BLENDOP_DISABLED); + REQUIRE(stateBits2.loadBits.structured.colorWriteRgb == 1); + REQUIRE(stateBits2.loadBits.structured.colorWriteAlpha == 1); + 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_0); + 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_BACK); + 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 == 0); + REQUIRE(stateBits3.loadBits.structured.polymodeLine == 1); + REQUIRE(stateBits3.loadBits.structured.depthWrite == 0); + REQUIRE(stateBits3.loadBits.structured.depthTestDisabled == 0); + REQUIRE(stateBits3.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL); + REQUIRE(stateBits3.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_2); + 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_ONE); + 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 == 1); + REQUIRE(stateBits4.loadBits.structured.depthTestDisabled == 0); + REQUIRE(stateBits4.loadBits.structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL); + REQUIRE(stateBits4.loadBits.structured.polygonOffset == GFXS_POLYGON_OFFSET_1); + REQUIRE(stateBits4.loadBits.structured.stencilFrontEnabled == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontPass == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontZFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilFrontFunc == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackEnabled == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackPass == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackZFail == 0); + REQUIRE(stateBits4.loadBits.structured.stencilBackFunc == 0); + + REQUIRE(material->thermalMaterial == nullptr); + } +} // namespace