Dump material tile and filter properties

This commit is contained in:
Jan 2022-08-06 18:47:28 +02:00
parent 0179d61451
commit c010355d4a
6 changed files with 205 additions and 70 deletions

View File

@ -627,6 +627,17 @@ namespace IW4
water_t* water; water_t* water;
}; };
enum MaterialTextureFilter
{
TEXTURE_FILTER_DISABLED = 0x0,
TEXTURE_FILTER_NEAREST = 0x1,
TEXTURE_FILTER_LINEAR = 0x2,
TEXTURE_FILTER_ANISO2X = 0x3,
TEXTURE_FILTER_ANISO4X = 0x4,
TEXTURE_FILTER_COUNT
};
enum SamplerStateBits_e enum SamplerStateBits_e
{ {
SAMPLER_FILTER_SHIFT = 0x0, SAMPLER_FILTER_SHIFT = 0x0,

View File

@ -409,6 +409,52 @@ namespace IW4
}; };
static_assert(std::extent_v<decltype(GdtStencilOpNames)> == static_cast<size_t>(StencilOp_e::COUNT)); static_assert(std::extent_v<decltype(GdtStencilOpNames)> == static_cast<size_t>(StencilOp_e::COUNT));
enum class TileMode_e
{
UNKNOWN,
TILE_BOTH,
TILE_HORIZONTAL,
TILE_VERTICAL,
NO_TILE,
COUNT
};
inline const char* GdtTileModeNames[]
{
"",
"tile both*",
"tile horizontal",
"tile vertical",
"no tile"
};
static_assert(std::extent_v<decltype(GdtTileModeNames)> == static_cast<size_t>(TileMode_e::COUNT));
enum class GdtFilter_e
{
UNKNOWN,
MIP_2X_BILINEAR,
MIP_4X_BILINEAR,
MIP_2X_TRILINEAR,
MIP_4X_TRILINEAR,
NOMIP_NEAREST,
NOMIP_BILINEAR,
COUNT
};
static const char* GdtSamplerFilterNames[]
{
"",
"mip standard (2x bilinear)*",
"mip expensive (4x bilinear)",
"mip more expensive (2x trilinear)",
"mip most expensive (4x trilinear)",
"nomip nearest",
"nomip bilinear"
};
static_assert(std::extent_v<decltype(GdtSamplerFilterNames)> == static_cast<size_t>(GdtFilter_e::COUNT));
enum GdtMaterialType enum GdtMaterialType
{ {
MATERIAL_TYPE_UNKNOWN, MATERIAL_TYPE_UNKNOWN,

View File

@ -526,61 +526,38 @@ namespace IW4
}; };
static_assert(std::extent_v<decltype(g_materialTypeInfo)> == MTL_TYPE_COUNT); static_assert(std::extent_v<decltype(g_materialTypeInfo)> == MTL_TYPE_COUNT);
static constexpr std::pair<uint32_t, const char*> KnownMaterialSource(const char* name) struct KnownMaterialTextureMap
{
const char* m_name;
const char* m_additional_property_suffix;
};
static constexpr std::pair<uint32_t, KnownMaterialTextureMap> MakeKnownTextureMap(const char* name, const char* additionalPropertySuffix)
{
return std::make_pair(Common::R_HashString(name, 0u), KnownMaterialTextureMap{name, additionalPropertySuffix});
}
inline std::unordered_map knownTextureMaps
{
MakeKnownTextureMap("colorMap", "Color"),
MakeKnownTextureMap("colorMap0", "Color00"),
MakeKnownTextureMap("colorMap1", "Color01"),
MakeKnownTextureMap("colorMap2", "Color02"),
MakeKnownTextureMap("normalMap", "Normal"),
MakeKnownTextureMap("specularMap", "Specular"),
MakeKnownTextureMap("detailMap", "Detail"),
};
static constexpr std::pair<uint32_t, const char*> MakeKnownConstantName(const char* name)
{ {
return std::make_pair(Common::R_HashString(name, 0u), name); return std::make_pair(Common::R_HashString(name, 0u), name);
} }
inline std::unordered_map knownMaterialSourceNames inline std::unordered_map knownConstantNames
{ {
KnownMaterialSource("colorMap"), MakeKnownConstantName("distortionScale"),
KnownMaterialSource("colorMap0"), MakeKnownConstantName("eyeOffsetParms"),
KnownMaterialSource("colorMap1"), MakeKnownConstantName("falloffBeginColor"),
KnownMaterialSource("colorMap2"), MakeKnownConstantName("falloffEndColor"),
KnownMaterialSource("colorMap3"),
KnownMaterialSource("colorMap4"),
KnownMaterialSource("colorMap5"),
KnownMaterialSource("colorMap6"),
KnownMaterialSource("colorMap7"),
KnownMaterialSource("normalMap"),
KnownMaterialSource("normalMap0"),
KnownMaterialSource("normalMap1"),
KnownMaterialSource("normalMap2"),
KnownMaterialSource("normalMap3"),
KnownMaterialSource("normalMap4"),
KnownMaterialSource("normalMap5"),
KnownMaterialSource("normalMap6"),
KnownMaterialSource("normalMap7"),
KnownMaterialSource("specularMap"),
KnownMaterialSource("specularMap0"),
KnownMaterialSource("specularMap1"),
KnownMaterialSource("specularMap2"),
KnownMaterialSource("specularMap3"),
KnownMaterialSource("specularMap4"),
KnownMaterialSource("specularMap5"),
KnownMaterialSource("specularMap6"),
KnownMaterialSource("specularMap7"),
KnownMaterialSource("detailMap"),
KnownMaterialSource("detailMap0"),
KnownMaterialSource("detailMap1"),
KnownMaterialSource("detailMap2"),
KnownMaterialSource("detailMap3"),
KnownMaterialSource("detailMap4"),
KnownMaterialSource("detailMap5"),
KnownMaterialSource("detailMap6"),
KnownMaterialSource("detailMap7"),
KnownMaterialSource("attenuationMap"),
KnownMaterialSource("attenuationMap0"),
KnownMaterialSource("attenuationMap1"),
KnownMaterialSource("attenuationMap2"),
KnownMaterialSource("attenuationMap3"),
KnownMaterialSource("attenuationMap4"),
KnownMaterialSource("attenuationMap5"),
KnownMaterialSource("attenuationMap6"),
KnownMaterialSource("attenuationMap7"),
KnownMaterialSource("distortionScale"),
KnownMaterialSource("eyeOffsetParms"),
KnownMaterialSource("falloffBeginColor"),
KnownMaterialSource("falloffEndColor"),
}; };
} }

View File

@ -142,9 +142,11 @@ namespace IW4
SetTechniqueSet("2d"); SetTechniqueSet("2d");
const auto colorMapName = ReadStringProperty("colorMap"); const auto colorMapName = ReadStringProperty("colorMap");
const auto tileColor = ReadEnumProperty<TileMode_e>("tileColor", GdtTileModeNames, std::extent_v<decltype(GdtTileModeNames)>);
const auto filterColor = ReadEnumProperty<GdtFilter_e>("filterColor", GdtSamplerFilterNames, std::extent_v<decltype(GdtSamplerFilterNames)>);
if (!colorMapName.empty()) if (!colorMapName.empty())
AddMapTexture("colorMap", TS_2D, colorMapName); AddMapTexture("colorMap", tileColor, filterColor, TS_2D, colorMapName);
else else
throw GdtReadingException("ColorMap may not be blank in 2d materials"); throw GdtReadingException("ColorMap may not be blank in 2d materials");
} }
@ -658,15 +660,59 @@ namespace IW4
return m_base_statebits; return m_base_statebits;
} }
void AddMapTexture(const std::string& typeName, const TextureSemantic semantic, const std::string& textureName) void AddMapTexture(const std::string& typeName, const TileMode_e tileMode, GdtFilter_e filterMode, const TextureSemantic semantic, const std::string& textureName)
{ {
MaterialTextureDef textureDef{}; MaterialTextureDef textureDef{};
textureDef.nameHash = Common::R_HashString(typeName.c_str()); textureDef.nameHash = Common::R_HashString(typeName.c_str());
textureDef.nameStart = typeName[0]; textureDef.nameStart = typeName[0];
textureDef.nameEnd = typeName[typeName.size() - 1]; textureDef.nameEnd = typeName[typeName.size() - 1];
textureDef.samplerState = 0; // TODO textureDef.samplerState = 0;
textureDef.semantic = static_cast<unsigned char>(semantic); textureDef.semantic = static_cast<unsigned char>(semantic);
switch (tileMode)
{
case TileMode_e::TILE_BOTH:
textureDef.samplerState |= SAMPLER_CLAMP_U | SAMPLER_CLAMP_V | SAMPLER_CLAMP_W;
break;
case TileMode_e::TILE_HORIZONTAL:
textureDef.samplerState |= SAMPLER_CLAMP_V;
break;
case TileMode_e::TILE_VERTICAL:
textureDef.samplerState |= SAMPLER_CLAMP_U;
break;
case TileMode_e::UNKNOWN:
case TileMode_e::NO_TILE:
break;
default:
assert(false);
break;
}
switch (filterMode)
{
case GdtFilter_e::MIP_2X_BILINEAR:
textureDef.samplerState |= SAMPLER_FILTER_ANISO2X | SAMPLER_MIPMAP_NEAREST;
break;
case GdtFilter_e::MIP_2X_TRILINEAR:
textureDef.samplerState |= SAMPLER_FILTER_ANISO2X | SAMPLER_MIPMAP_LINEAR;
break;
case GdtFilter_e::MIP_4X_BILINEAR:
textureDef.samplerState |= SAMPLER_FILTER_ANISO4X | SAMPLER_MIPMAP_NEAREST;
break;
case GdtFilter_e::MIP_4X_TRILINEAR:
textureDef.samplerState |= SAMPLER_FILTER_ANISO4X | SAMPLER_MIPMAP_LINEAR;
break;
case GdtFilter_e::NOMIP_NEAREST:
textureDef.samplerState |= SAMPLER_FILTER_NEAREST | SAMPLER_MIPMAP_DISABLED;
break;
case GdtFilter_e::NOMIP_BILINEAR:
textureDef.samplerState |= SAMPLER_FILTER_LINEAR | SAMPLER_MIPMAP_DISABLED;
break;
default:
assert(false);
break;
}
auto* image = reinterpret_cast<XAssetInfo<GfxImage>*>(m_manager->LoadDependency(ASSET_TYPE_IMAGE, textureName)); auto* image = reinterpret_cast<XAssetInfo<GfxImage>*>(m_manager->LoadDependency(ASSET_TYPE_IMAGE, textureName));
if (image == nullptr) if (image == nullptr)
@ -1015,7 +1061,7 @@ bool AssetLoaderMaterial::LoadFromGdt(const std::string& assetName, IGdtQueryabl
if (loader.Load()) if (loader.Load())
manager->AddAsset(ASSET_TYPE_MATERIAL, assetName, loader.GetMaterial(), loader.GetDependencies(), std::vector<scr_string_t>()); manager->AddAsset(ASSET_TYPE_MATERIAL, assetName, loader.GetMaterial(), loader.GetDependencies(), std::vector<scr_string_t>());
} }
catch(const SkipMaterialException&) catch (const SkipMaterialException&)
{ {
return false; return false;
} }

View File

@ -19,6 +19,7 @@
using namespace IW4; using namespace IW4;
using json = nlohmann::json; using json = nlohmann::json;
using namespace std::string_literals;
namespace IW4 namespace IW4
{ {
@ -136,10 +137,10 @@ namespace IW4
{"semantic", ArrayEntry(semanticNames, entry.semantic)} {"semantic", ArrayEntry(semanticNames, entry.semantic)}
}; };
const auto knownMaterialSourceName = knownMaterialSourceNames.find(entry.nameHash); const auto knownMaterialSourceName = knownTextureMaps.find(entry.nameHash);
if (knownMaterialSourceName != knownMaterialSourceNames.end()) if (knownMaterialSourceName != knownTextureMaps.end())
{ {
jEntry["name"] = knownMaterialSourceName->second; jEntry["name"] = knownMaterialSourceName->second.m_name;
} }
else else
{ {
@ -191,8 +192,8 @@ namespace IW4
} }
else else
{ {
const auto knownMaterialSourceName = knownMaterialSourceNames.find(entry.nameHash); const auto knownMaterialSourceName = knownConstantNames.find(entry.nameHash);
if (knownMaterialSourceName != knownMaterialSourceNames.end()) if (knownMaterialSourceName != knownConstantNames.end())
{ {
jEntry["name"] = knownMaterialSourceName->second; jEntry["name"] = knownMaterialSourceName->second;
} }
@ -1351,8 +1352,8 @@ namespace IW4
for (auto i = 0u; i < m_material->textureCount; i++) for (auto i = 0u; i < m_material->textureCount; i++)
{ {
const auto& entry = m_material->textureTable[i]; const auto& entry = m_material->textureTable[i];
const auto knownMaterialSourceName = knownMaterialSourceNames.find(entry.nameHash); const auto knownMaterialSourceName = knownTextureMaps.find(entry.nameHash);
if (knownMaterialSourceName == knownMaterialSourceNames.end()) if (knownMaterialSourceName == knownTextureMaps.end())
{ {
assert(false); assert(false);
std::cout << "Unknown material texture source name hash: 0x" << std::hex << entry.nameHash << " (" << entry.nameStart << "..." << entry.nameEnd << ")\n"; std::cout << "Unknown material texture source name hash: 0x" << std::hex << entry.nameHash << " (" << entry.nameStart << "..." << entry.nameEnd << ")\n";
@ -1373,7 +1374,52 @@ namespace IW4
imageName = AssetName(entry.u.water->image->name); imageName = AssetName(entry.u.water->image->name);
} }
SetValue(knownMaterialSourceName->second, imageName); TileMode_e tileMode;
if (entry.samplerState & SAMPLER_CLAMP_U && entry.samplerState & SAMPLER_CLAMP_V && entry.samplerState & SAMPLER_CLAMP_W)
tileMode = TileMode_e::TILE_BOTH;
else if (entry.samplerState & SAMPLER_CLAMP_U)
tileMode = TileMode_e::TILE_VERTICAL;
else if (entry.samplerState & SAMPLER_CLAMP_V)
tileMode = TileMode_e::TILE_HORIZONTAL;
else
tileMode = TileMode_e::NO_TILE;
auto filter = GdtFilter_e::UNKNOWN;
if ((entry.samplerState & SAMPLER_FILTER_MASK) == SAMPLER_FILTER_ANISO2X)
{
if (entry.samplerState & SAMPLER_MIPMAP_NEAREST)
filter = GdtFilter_e::MIP_2X_BILINEAR;
else if (entry.samplerState & SAMPLER_MIPMAP_LINEAR)
filter = GdtFilter_e::MIP_2X_TRILINEAR;
}
else if ((entry.samplerState & SAMPLER_FILTER_MASK) == SAMPLER_FILTER_ANISO4X)
{
if (entry.samplerState & SAMPLER_MIPMAP_NEAREST)
filter = GdtFilter_e::MIP_4X_BILINEAR;
else if (entry.samplerState & SAMPLER_MIPMAP_LINEAR)
filter = GdtFilter_e::MIP_4X_TRILINEAR;
}
else if ((entry.samplerState & SAMPLER_FILTER_MASK) == SAMPLER_FILTER_NEAREST)
{
assert((entry.samplerState & SAMPLER_MIPMAP_MASK) == SAMPLER_MIPMAP_DISABLED);
filter = GdtFilter_e::NOMIP_NEAREST;
}
else if ((entry.samplerState & SAMPLER_FILTER_MASK) == SAMPLER_FILTER_LINEAR)
{
assert((entry.samplerState & SAMPLER_MIPMAP_MASK) == SAMPLER_MIPMAP_DISABLED);
filter = GdtFilter_e::NOMIP_BILINEAR;
}
assert(filter != GdtFilter_e::UNKNOWN);
if (filter == GdtFilter_e::UNKNOWN)
{
std::cout << "Unknown filter/mipmap combination: " << entry.samplerState << "\n";
continue;
}
SetValue(knownMaterialSourceName->second.m_name, imageName);
SetValue("tile"s + knownMaterialSourceName->second.m_additional_property_suffix, GdtTileModeNames[static_cast<size_t>(tileMode)]);
SetValue("filter"s + knownMaterialSourceName->second.m_additional_property_suffix, GdtSamplerFilterNames[static_cast<size_t>(filter)]);
} }
} }

View File

@ -212,18 +212,27 @@ namespace IW4
Indent(); Indent();
m_stream << codeDestAccessor << " = material."; m_stream << codeDestAccessor << " = material.";
const auto knownMaterialSource = knownMaterialSourceNames.find(arg.u.nameHash); const auto knownConstantName = knownConstantNames.find(arg.u.nameHash);
if (knownMaterialSource != knownMaterialSourceNames.end()) if (knownConstantName != knownConstantNames.end())
{ {
m_stream << knownMaterialSource->second; m_stream << knownConstantName->second;
} }
else else
{ {
const auto shaderArgNameHash = Common::R_HashString(targetShaderArg->m_name.c_str(), 0u); const auto knownMaterialTextureName = knownTextureMaps.find(arg.u.nameHash);
if (shaderArgNameHash == arg.u.nameHash)
m_stream << targetShaderArg->m_name; if(knownMaterialTextureName != knownTextureMaps.end())
{
m_stream << knownConstantName->second;
}
else else
m_stream << "#0x" << std::hex << arg.u.nameHash; {
const auto shaderArgNameHash = Common::R_HashString(targetShaderArg->m_name.c_str(), 0u);
if (shaderArgNameHash == arg.u.nameHash)
m_stream << targetShaderArg->m_name;
else
m_stream << "#0x" << std::hex << arg.u.nameHash;
}
} }
m_stream << ";\n"; m_stream << ";\n";