Write Statebits data to gdt materials

This commit is contained in:
Jan 2022-05-02 21:11:51 +02:00
parent b94c5b381d
commit cc2f0ca487
3 changed files with 337 additions and 80 deletions

View File

@ -729,10 +729,10 @@ namespace IW4
GFXS0_ATEST_GE_128 = 0x3000,
GFXS0_ATEST_MASK = 0x3000,
GFXS0_CULL_SHIFT = 0xE,
GFXS0_CULL_NONE = 0x4000,
GFXS0_CULL_BACK = 0x8000,
GFXS0_CULL_FRONT = 0xC000,
GFXS0_CULL_SHIFT = 0xE,
GFXS0_CULL_MASK = 0xC000,
GFXS0_SRCBLEND_ALPHA_SHIFT = 0x10,
@ -752,18 +752,18 @@ namespace IW4
GFXS1_DEPTHWRITE = 0x1,
GFXS1_DEPTHTEST_DISABLE = 0x2,
GFXS1_DEPTHTEST_SHIFT = 0x2,
GFXS1_DEPTHTEST_ALWAYS = 0x0,
GFXS1_DEPTHTEST_LESS = 0x4,
GFXS1_DEPTHTEST_EQUAL = 0x8,
GFXS1_DEPTHTEST_LESSEQUAL = 0xC,
GFXS1_DEPTHTEST_SHIFT = 0x2,
GFXS1_DEPTHTEST_MASK = 0xC,
GFXS1_POLYGON_OFFSET_SHIFT = 0x4,
GFXS1_POLYGON_OFFSET_0 = 0x0,
GFXS1_POLYGON_OFFSET_1 = 0x10,
GFXS1_POLYGON_OFFSET_2 = 0x20,
GFXS1_POLYGON_OFFSET_SHADOWMAP = 0x30,
GFXS1_POLYGON_OFFSET_SHIFT = 0x4,
GFXS1_POLYGON_OFFSET_MASK = 0x30,
GFXS1_STENCIL_FRONT_ENABLE = 0x40,

View File

@ -108,4 +108,199 @@ namespace IW4
"slush"
};
static_assert(std::extent_v<decltype(surfaceTypeNames)> == SURF_TYPE_NUM);
enum class BlendFunc_e
{
UNKNOWN,
CUSTOM,
REPLACE,
BLEND,
ADD,
MULTIPLY,
SCREEN_ADD,
COUNT
};
inline const char* GdtBlendFuncNames[]
{
"",
"Custom",
"Replace*",
"Blend",
"Add",
"Multiply",
"Screen Add"
};
static_assert(std::extent_v<decltype(GdtBlendFuncNames)> == static_cast<size_t>(BlendFunc_e::COUNT));
enum class BlendOp_e
{
UNKNOWN,
DISABLE,
ADD,
SUBTRACT,
REV_SUBTRACT,
MIN,
MAX,
COUNT
};
inline const char* GdtBlendOpNames[]
{
"",
"Disable",
"Add*",
"Subtract",
"RevSubtract",
"Min",
"Max"
};
static_assert(std::extent_v<decltype(GdtBlendOpNames)> == static_cast<size_t>(BlendOp_e::COUNT));
enum class CustomBlendFunc_e
{
UNKNOWN,
DISABLED,
ZERO,
ONE,
SRC_COLOR,
INV_SRC_COLOR,
SRC_ALPHA,
INV_SRC_ALPHA,
DST_ALPHA,
INV_DST_ALPHA,
DEST_COLOR,
INV_DST_COLOR,
COUNT
};
inline const char* GdtCustomBlendFuncNames[]
{
"",
"Disable",
"Zero",
"One*",
"SrcColor",
"InvSrcColor",
"SrcAlpha",
"InvSrcAlpha",
"DestAlpha",
"InvDestAlpha",
"DestColor",
"InvDestColor"
};
static_assert(std::extent_v<decltype(GdtCustomBlendFuncNames)> == static_cast<size_t>(CustomBlendFunc_e::COUNT));
enum class AlphaTest_e
{
UNKNOWN,
ALWAYS,
GT0,
LT128,
GE128,
COUNT
};
inline const char* GdtAlphaTestNames[]
{
"",
"Always*",
"GT0",
"LT128",
"GE128"
};
static_assert(std::extent_v<decltype(GdtAlphaTestNames)> == static_cast<size_t>(AlphaTest_e::COUNT));
enum class DepthTest_e
{
UNKNOWN,
LESS_EQUAL,
LESS,
EQUAL,
ALWAYS,
DISABLE,
COUNT
};
inline const char* GdtDepthTestNames[]
{
"",
"LessEqual*",
"Less",
"Equal",
"Always",
"Disable"
};
static_assert(std::extent_v<decltype(GdtDepthTestNames)> == static_cast<size_t>(DepthTest_e::COUNT));
enum class StateBitsEnabledStatus_e
{
UNKNOWN,
ENABLED,
DISABLED,
COUNT
};
inline const char* GdtStateBitsEnabledStatusNames[]
{
"",
"Enable",
"Disable"
};
static_assert(std::extent_v<decltype(GdtStateBitsEnabledStatusNames)> == static_cast<size_t>(StateBitsEnabledStatus_e::COUNT));
inline const char* GdtStateBitsOnOffStatusNames[]
{
"",
"On",
"Off"
};
static_assert(std::extent_v<decltype(GdtStateBitsOnOffStatusNames)> == static_cast<size_t>(StateBitsEnabledStatus_e::COUNT));
enum class CullFace_e
{
UNKNOWN,
NONE,
BACK,
FRONT,
COUNT
};
inline const char* GdtCullFaceNames[]
{
"",
"None",
"Back*",
"Front"
};
static_assert(std::extent_v<decltype(GdtCullFaceNames)> == static_cast<size_t>(CullFace_e::COUNT));
enum class PolygonOffset_e
{
UNKNOWN,
OFFSET_0,
OFFSET_1,
OFFSET_2,
OFFSET_SHADOW_MAP,
COUNT
};
inline const char* GdtPolygonOffsetNames[]
{
"",
"0",
"1",
"2",
"shadowMap"
};
static_assert(std::extent_v<decltype(GdtPolygonOffsetNames)> == static_cast<size_t>(PolygonOffset_e::COUNT));
}

View File

@ -540,82 +540,6 @@ namespace IW4
bool m_color_o_flag = false;
};
enum class BlendFunc_e
{
UNKNOWN,
CUSTOM,
REPLACE,
BLEND,
ADD,
MULTIPLY,
SCREEN_ADD
};
enum class BlendOp_e
{
UNKNOWN,
ADD,
SUBTRACT,
REV_SUBTRACT,
MIN,
MAX,
DISABLE
};
enum class CustomBlendFunc_e
{
UNKNOWN,
ONE,
ZERO,
SRC_COLOR,
INV_SRC_COLOR,
SRC_ALPHA,
INV_SRC_ALPHA,
DST_ALPHA,
INV_DST_ALPHA,
DEST_COLOR,
INV_DST_COLOR
};
enum class AlphaTest_e
{
UNKNOWN,
ALWAYS,
GE128
};
enum class DepthTest_e
{
UNKNOWN,
LESS_EQUAL,
LESS,
EQUAL,
ALWAYS,
DISABLE
};
enum class StateBitsEnabledStatus_e
{
UNKNOWN,
ENABLED,
DISABLED
};
enum class CullFace_e
{
UNKNOWN,
FRONT,
BACK,
NONE
};
enum class PolygonOffset
{
UNKNOWN,
STATIC_DECAL,
WEAPON_IMPACT
};
class StateBitsInfo
{
public:
@ -630,7 +554,7 @@ namespace IW4
DepthTest_e m_depth_test = DepthTest_e::UNKNOWN;
StateBitsEnabledStatus_e m_depth_write = StateBitsEnabledStatus_e::UNKNOWN;
CullFace_e m_cull_face = CullFace_e::UNKNOWN;
PolygonOffset m_polygon_offset = PolygonOffset::UNKNOWN;
PolygonOffset_e m_polygon_offset = PolygonOffset_e::UNKNOWN;
StateBitsEnabledStatus_e m_color_write_rgb = StateBitsEnabledStatus_e::UNKNOWN;
StateBitsEnabledStatus_e m_color_write_alpha = StateBitsEnabledStatus_e::UNKNOWN;
};
@ -645,6 +569,11 @@ namespace IW4
const Material* m_material;
GdtEntry m_entry;
void SetValue(const std::string& key, const char* value)
{
m_entry.m_properties.emplace(std::make_pair(key, value));
}
void SetValue(const std::string& key, std::string value)
{
m_entry.m_properties.emplace(std::make_pair(key, std::move(value)));
@ -657,6 +586,11 @@ namespace IW4
m_entry.m_properties.emplace(std::make_pair(key, ss.str()));
}
void SetValue(const std::string& key, const bool value)
{
m_entry.m_properties.emplace(std::make_pair(key, value ? "1" : "0"));
}
template <typename T,
typename = typename std::enable_if_t<std::is_arithmetic_v<T>, T>>
void SetValue(const std::string& key, T value)
@ -959,12 +893,140 @@ namespace IW4
}
}
template <typename T>
T StateBitsToEnum(const unsigned input, const size_t mask, const size_t shift)
{
const unsigned value = (input & mask) >> shift;
return value >= (static_cast<unsigned>(T::COUNT) - 1) ? T::UNKNOWN : static_cast<T>(value + 1);
}
void ExamineStateBitsInfo()
{
if (!m_material->stateBitsTable || m_material->stateBitsCount == 0)
return;
// This assumes the statemap of these techniques is passthrough which it is most likely not
// This should still not produce any wrong values
GfxStateBits stateBits{};
if (m_material->stateBitsEntry[TECHNIQUE_LIT] < m_material->stateBitsCount)
stateBits = m_material->stateBitsTable[m_material->stateBitsEntry[TECHNIQUE_LIT]];
else if (m_material->stateBitsEntry[TECHNIQUE_EMISSIVE] < m_material->stateBitsCount)
stateBits = m_material->stateBitsTable[m_material->stateBitsEntry[TECHNIQUE_EMISSIVE]];
else if (m_material->stateBitsEntry[TECHNIQUE_UNLIT] < m_material->stateBitsCount)
stateBits = m_material->stateBitsTable[m_material->stateBitsEntry[TECHNIQUE_UNLIT]];
else if (m_material->stateBitsEntry[TECHNIQUE_DEPTH_PREPASS] < m_material->stateBitsCount)
stateBits = m_material->stateBitsTable[m_material->stateBitsEntry[TECHNIQUE_DEPTH_PREPASS]];
else
{
assert(false);
return;
}
if (m_state_bits_info.m_custom_blend_op_rgb == BlendOp_e::UNKNOWN)
m_state_bits_info.m_custom_blend_op_rgb = StateBitsToEnum<BlendOp_e>(stateBits.loadBits[0], GFXS0_BLENDOP_RGB_MASK, GFXS0_BLENDOP_RGB_SHIFT);
if (m_state_bits_info.m_custom_blend_op_alpha == BlendOp_e::UNKNOWN)
m_state_bits_info.m_custom_blend_op_alpha = StateBitsToEnum<BlendOp_e>(stateBits.loadBits[0], GFXS0_BLENDOP_ALPHA_MASK, GFXS0_BLENDOP_ALPHA_SHIFT);
if (m_state_bits_info.m_custom_src_blend_func == CustomBlendFunc_e::UNKNOWN)
m_state_bits_info.m_custom_src_blend_func = StateBitsToEnum<CustomBlendFunc_e>(stateBits.loadBits[0], GFXS0_SRCBLEND_RGB_MASK, GFXS0_SRCBLEND_RGB_SHIFT);
if (m_state_bits_info.m_custom_dst_blend_func == CustomBlendFunc_e::UNKNOWN)
m_state_bits_info.m_custom_dst_blend_func = StateBitsToEnum<CustomBlendFunc_e>(stateBits.loadBits[0], GFXS0_DSTBLEND_RGB_MASK, GFXS0_DSTBLEND_RGB_SHIFT);
if (m_state_bits_info.m_custom_src_blend_func_alpha == CustomBlendFunc_e::UNKNOWN)
m_state_bits_info.m_custom_src_blend_func_alpha = StateBitsToEnum<CustomBlendFunc_e>(stateBits.loadBits[0], GFXS0_SRCBLEND_ALPHA_MASK, GFXS0_SRCBLEND_ALPHA_SHIFT);
if (m_state_bits_info.m_custom_dst_blend_func_alpha == CustomBlendFunc_e::UNKNOWN)
m_state_bits_info.m_custom_dst_blend_func_alpha = StateBitsToEnum<CustomBlendFunc_e>(stateBits.loadBits[0], GFXS0_DSTBLEND_ALPHA_MASK, GFXS0_DSTBLEND_ALPHA_SHIFT);
if (m_state_bits_info.m_alpha_test == AlphaTest_e::UNKNOWN)
{
if (stateBits.loadBits[0] & GFXS0_ATEST_DISABLE)
m_state_bits_info.m_alpha_test = AlphaTest_e::ALWAYS;
else if (stateBits.loadBits[0] & GFXS0_ATEST_GE_128)
m_state_bits_info.m_alpha_test = AlphaTest_e::GE128;
else if (stateBits.loadBits[0] & GFXS0_ATEST_GT_0)
m_state_bits_info.m_alpha_test = AlphaTest_e::GT0;
else if (stateBits.loadBits[0] & GFXS0_ATEST_LT_128)
m_state_bits_info.m_alpha_test = AlphaTest_e::LT128;
else
assert(false);
}
if (m_state_bits_info.m_depth_test == DepthTest_e::UNKNOWN)
{
if (stateBits.loadBits[1] & GFXS1_DEPTHTEST_DISABLE)
m_state_bits_info.m_depth_test = DepthTest_e::DISABLE;
else if (stateBits.loadBits[1] & GFXS1_DEPTHTEST_LESSEQUAL)
m_state_bits_info.m_depth_test = DepthTest_e::LESS_EQUAL;
else if (stateBits.loadBits[1] & GFXS1_DEPTHTEST_LESS)
m_state_bits_info.m_depth_test = DepthTest_e::LESS;
else if (stateBits.loadBits[1] & GFXS1_DEPTHTEST_EQUAL)
m_state_bits_info.m_depth_test = DepthTest_e::EQUAL;
else
m_state_bits_info.m_depth_test = DepthTest_e::ALWAYS;
}
if (m_state_bits_info.m_depth_write == StateBitsEnabledStatus_e::UNKNOWN)
m_state_bits_info.m_depth_write = (stateBits.loadBits[1] & GFXS1_DEPTHWRITE) ? StateBitsEnabledStatus_e::ENABLED : StateBitsEnabledStatus_e::DISABLED;
if (m_state_bits_info.m_cull_face == CullFace_e::UNKNOWN)
{
if (stateBits.loadBits[0] & GFXS0_CULL_NONE)
m_state_bits_info.m_cull_face = CullFace_e::NONE;
else if (stateBits.loadBits[0] & GFXS0_CULL_BACK)
m_state_bits_info.m_cull_face = CullFace_e::BACK;
else if (stateBits.loadBits[0] & GFXS0_CULL_FRONT)
m_state_bits_info.m_cull_face = CullFace_e::FRONT;
else
assert(false);
}
if (m_state_bits_info.m_polygon_offset == PolygonOffset_e::UNKNOWN)
m_state_bits_info.m_polygon_offset = StateBitsToEnum<PolygonOffset_e>(stateBits.loadBits[1], GFXS1_POLYGON_OFFSET_MASK, GFXS1_POLYGON_OFFSET_SHIFT);
if (m_state_bits_info.m_color_write_rgb == StateBitsEnabledStatus_e::UNKNOWN)
m_state_bits_info.m_color_write_rgb = (stateBits.loadBits[0] & GFXS0_COLORWRITE_RGB) ? StateBitsEnabledStatus_e::ENABLED : StateBitsEnabledStatus_e::DISABLED;
if (m_state_bits_info.m_color_write_alpha == StateBitsEnabledStatus_e::UNKNOWN)
m_state_bits_info.m_color_write_alpha = (stateBits.loadBits[0] & GFXS0_COLORWRITE_ALPHA) ? StateBitsEnabledStatus_e::ENABLED : StateBitsEnabledStatus_e::DISABLED;
}
void SetMaterialTypeValues()
{
ExamineTechsetInfo();
ExamineStateBitsInfo();
SetValue("materialType", GdtMaterialTypeNames[static_cast<size_t>(m_techset_info.m_gdt_material_type)]);
SetValue("customTemplate", GdtCustomMaterialTypeNames[static_cast<size_t>(m_techset_info.m_gdt_custom_material_type)]);
SetValue("customString", m_techset_info.m_gdt_custom_string);
SetValue("noCastShadow", m_techset_info.m_no_cast_shadow);
SetValue("noReceiveDynamicShadow", m_techset_info.m_no_receive_dynamic_shadow);
SetValue("noFog", m_techset_info.m_no_fog);
SetValue("texScroll", m_techset_info.m_tex_scroll);
SetValue("uvAnim", m_techset_info.m_uv_anim);
// TODO: These are not good names, change when known what they do
SetValue("specularP", m_techset_info.m_specular_p_flag);
SetValue("colorO", m_techset_info.m_color_o_flag);
SetValue("blendFunc", GdtBlendFuncNames[static_cast<size_t>(m_state_bits_info.m_blend_func)]);
SetValue("customBlendOpRgb", GdtBlendOpNames[static_cast<size_t>(m_state_bits_info.m_custom_blend_op_rgb)]);
SetValue("customBlendOpAlpha", GdtBlendOpNames[static_cast<size_t>(m_state_bits_info.m_custom_blend_op_alpha)]);
SetValue("srcCustomBlendFunc", GdtCustomBlendFuncNames[static_cast<size_t>(m_state_bits_info.m_custom_src_blend_func)]);
SetValue("destCustomBlendFunc", GdtCustomBlendFuncNames[static_cast<size_t>(m_state_bits_info.m_custom_dst_blend_func)]);
SetValue("srcCustomBlendFuncAlpha", GdtCustomBlendFuncNames[static_cast<size_t>(m_state_bits_info.m_custom_src_blend_func_alpha)]);
SetValue("destCustomBlendFuncAlpha", GdtCustomBlendFuncNames[static_cast<size_t>(m_state_bits_info.m_custom_dst_blend_func_alpha)]);
SetValue("alphaTest", GdtAlphaTestNames[static_cast<size_t>(m_state_bits_info.m_alpha_test)]);
SetValue("depthTest", GdtDepthTestNames[static_cast<size_t>(m_state_bits_info.m_depth_test)]);
SetValue("depthWrite", GdtStateBitsOnOffStatusNames[static_cast<size_t>(m_state_bits_info.m_depth_write)]);
SetValue("cullFace", GdtCullFaceNames[static_cast<size_t>(m_state_bits_info.m_cull_face)]);
SetValue("polygonOffset", GdtPolygonOffsetNames[static_cast<size_t>(m_state_bits_info.m_polygon_offset)]);
SetValue("colorWriteRed", GdtStateBitsEnabledStatusNames[static_cast<size_t>(m_state_bits_info.m_color_write_rgb)]);
SetValue("colorWriteGreen", GdtStateBitsEnabledStatusNames[static_cast<size_t>(m_state_bits_info.m_color_write_rgb)]);
SetValue("colorWriteBlue", GdtStateBitsEnabledStatusNames[static_cast<size_t>(m_state_bits_info.m_color_write_rgb)]);
SetValue("colorWriteAlpha", GdtStateBitsEnabledStatusNames[static_cast<size_t>(m_state_bits_info.m_color_write_alpha)]);
}
void SetTextureTableValues()