diff --git a/src/Common/Game/IW3/IW3_Assets.h b/src/Common/Game/IW3/IW3_Assets.h index 145e03c7..efb48b54 100644 --- a/src/Common/Game/IW3/IW3_Assets.h +++ b/src/Common/Game/IW3/IW3_Assets.h @@ -555,33 +555,44 @@ namespace IW3 { GFXS0_SRCBLEND_RGB_SHIFT = 0x0, GFXS0_SRCBLEND_RGB_MASK = 0xF, + GFXS0_DSTBLEND_RGB_SHIFT = 0x4, GFXS0_DSTBLEND_RGB_MASK = 0xF0, + GFXS0_BLENDOP_RGB_SHIFT = 0x8, GFXS0_BLENDOP_RGB_MASK = 0x700, GFXS0_BLEND_RGB_MASK = 0x7FF, + GFXS0_ATEST_DISABLE = 0x800, GFXS0_ATEST_GT_0 = 0x1000, GFXS0_ATEST_LT_128 = 0x2000, 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_MASK = 0xC000, + GFXS0_SRCBLEND_ALPHA_SHIFT = 0x10, GFXS0_SRCBLEND_ALPHA_MASK = 0xF0000, + GFXS0_DSTBLEND_ALPHA_SHIFT = 0x14, GFXS0_DSTBLEND_ALPHA_MASK = 0xF00000, + GFXS0_BLENDOP_ALPHA_SHIFT = 0x18, GFXS0_BLENDOP_ALPHA_MASK = 0x7000000, GFXS0_BLEND_ALPHA_MASK = 0x7FF0000, + GFXS0_COLORWRITE_RGB = 0x8000000, GFXS0_COLORWRITE_ALPHA = 0x10000000, GFXS0_COLORWRITE_MASK = 0x18000000, + GFXS0_POLYMODE_LINE = 0x80000000, + GFXS1_DEPTHWRITE = 0x1, + GFXS1_DEPTHTEST_DISABLE = 0x2, GFXS1_DEPTHTEST_SHIFT = 0x2, GFXS1_DEPTHTEST_ALWAYS = 0x0, @@ -589,25 +600,30 @@ namespace IW3 GFXS1_DEPTHTEST_EQUAL = 0x8, GFXS1_DEPTHTEST_LESSEQUAL = 0xC, 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_MASK = 0x30, + GFXS1_STENCIL_FRONT_ENABLE = 0x40, GFXS1_STENCIL_BACK_ENABLE = 0x80, GFXS1_STENCIL_MASK = 0xC0, + GFXS1_STENCIL_FRONT_PASS_SHIFT = 0x8, GFXS1_STENCIL_FRONT_FAIL_SHIFT = 0xB, GFXS1_STENCIL_FRONT_ZFAIL_SHIFT = 0xE, GFXS1_STENCIL_FRONT_FUNC_SHIFT = 0x11, GFXS1_STENCIL_FRONT_MASK = 0xFFF00, + GFXS1_STENCIL_BACK_PASS_SHIFT = 0x14, GFXS1_STENCIL_BACK_FAIL_SHIFT = 0x17, GFXS1_STENCIL_BACK_ZFAIL_SHIFT = 0x1A, GFXS1_STENCIL_BACK_FUNC_SHIFT = 0x1D, GFXS1_STENCIL_BACK_MASK = 0xFFF00000, + GFXS1_STENCILFUNC_FRONTBACK_MASK = 0xE00E0000, GFXS1_STENCILOP_FRONTBACK_MASK = 0x1FF1FF00, }; diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index 59ce5b3b..85a5148b 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -696,6 +696,21 @@ namespace IW4 GFXS_BLENDOP_MASK = 0x7, }; + enum GfxStencilFunc + { + GFXS_STENCILFUNC_NEVER = 0x0, + GFXS_STENCILFUNC_LESS = 0x1, + GFXS_STENCILFUNC_EQUAL = 0x2, + GFXS_STENCILFUNC_LESSEQUAL = 0x3, + GFXS_STENCILFUNC_GREATER = 0x4, + GFXS_STENCILFUNC_NOTEQUAL = 0x5, + GFXS_STENCILFUNC_GREATEREQUAL = 0x6, + GFXS_STENCILFUNC_ALWAYS = 0x7, + + GFXS_STENCILFUNC_COUNT, + GFXS_STENCILFUNC_MASK = 0x7 + }; + enum GfxStencilOp { GFXS_STENCILOP_KEEP = 0x0, @@ -737,8 +752,10 @@ namespace IW4 GFXS0_SRCBLEND_ALPHA_SHIFT = 0x10, GFXS0_SRCBLEND_ALPHA_MASK = 0xF0000, + GFXS0_DSTBLEND_ALPHA_SHIFT = 0x14, GFXS0_DSTBLEND_ALPHA_MASK = 0xF00000, + GFXS0_BLENDOP_ALPHA_SHIFT = 0x18, GFXS0_BLENDOP_ALPHA_MASK = 0x7000000, GFXS0_BLEND_ALPHA_MASK = 0x7FF0000, @@ -751,6 +768,7 @@ namespace IW4 GFXS0_POLYMODE_LINE = 0x80000000, GFXS1_DEPTHWRITE = 0x1, + GFXS1_DEPTHTEST_DISABLE = 0x2, GFXS1_DEPTHTEST_ALWAYS = 0x0, GFXS1_DEPTHTEST_LESS = 0x4, @@ -771,15 +789,29 @@ namespace IW4 GFXS1_STENCIL_MASK = 0xC0, GFXS1_STENCIL_FRONT_PASS_SHIFT = 0x8, + GFXS1_STENCIL_FRONT_PASS_MASK = 0x700, + GFXS1_STENCIL_FRONT_FAIL_SHIFT = 0xB, + GFXS1_STENCIL_FRONT_FAIL_MASK = 0x3800, + GFXS1_STENCIL_FRONT_ZFAIL_SHIFT = 0xE, + GFXS1_STENCIL_FRONT_ZFAIL_MASK = 0x1C000, + GFXS1_STENCIL_FRONT_FUNC_SHIFT = 0x11, + GFXS1_STENCIL_FRONT_FUNC_MASK = 0xE0000, GFXS1_STENCIL_FRONT_MASK = 0xFFF00, GFXS1_STENCIL_BACK_PASS_SHIFT = 0x14, + GFXS1_STENCIL_BACK_PASS_MASK = 0x700000, + GFXS1_STENCIL_BACK_FAIL_SHIFT = 0x17, + GFXS1_STENCIL_BACK_FAIL_MASK = 0x3800000, + GFXS1_STENCIL_BACK_ZFAIL_SHIFT = 0x1A, + GFXS1_STENCIL_BACK_ZFAIL_MASK = 0x1C000000, + GFXS1_STENCIL_BACK_FUNC_SHIFT = 0x1D, + GFXS1_STENCIL_BACK_FUNC_MASK = 0xE0000000, GFXS1_STENCIL_BACK_MASK = 0xFFF00000, GFXS1_STENCILFUNC_FRONTBACK_MASK = 0xE00E0000, diff --git a/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h b/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h index 907ded7e..748b60f3 100644 --- a/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h +++ b/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h @@ -303,4 +303,62 @@ namespace IW4 "shadowMap" }; static_assert(std::extent_v == static_cast(PolygonOffset_e::COUNT)); + + enum class StencilFunc_e + { + UNKNOWN, + NEVER, + LESS, + EQUAL, + LESS_EQUAL, + GREATER, + NOT_EQUAL, + GREATER_EQUAL, + ALWAYS, + + COUNT + }; + + inline const char* GdtStencilFuncNames[] + { + "", + "Never", + "Less", + "Equal", + "LessEqual", + "Greater", + "NotEqual", + "GreaterEqual", + "Always" + }; + static_assert(std::extent_v == static_cast(StencilFunc_e::COUNT)); + + enum class StencilOp_e + { + UNKNOWN, + KEEP, + ZERO, + REPLACE, + INCR_SAT, + DECR_SAT, + INVERT, + INCR, + DECR, + + COUNT + }; + + inline const char* GdtStencilOpNames[] + { + "", + "Keep", + "Zero", + "Replace", + "IncrSat", + "DecrSat", + "Invert", + "Incr", + "Decr" + }; + static_assert(std::extent_v == static_cast(StencilOp_e::COUNT)); } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp index b0fc9efa..66ae2a7a 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp @@ -557,6 +557,15 @@ namespace IW4 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; + StateBitsEnabledStatus_e m_gamma_write = StateBitsEnabledStatus_e::UNKNOWN; + StencilFunc_e m_stencil_front_func = StencilFunc_e::UNKNOWN; + StencilOp_e m_stencil_front_fail = StencilOp_e::UNKNOWN; + StencilOp_e m_stencil_front_zfail = StencilOp_e::UNKNOWN; + StencilOp_e m_stencil_front_pass = StencilOp_e::UNKNOWN; + StencilFunc_e m_stencil_back_func = StencilFunc_e::UNKNOWN; + StencilOp_e m_stencil_back_fail = StencilOp_e::UNKNOWN; + StencilOp_e m_stencil_back_zfail = StencilOp_e::UNKNOWN; + StencilOp_e m_stencil_back_pass = StencilOp_e::UNKNOWN; }; class MaterialGdtDumper @@ -893,6 +902,77 @@ namespace IW4 } } + class BlendFuncParameters + { + public: + const BlendFunc_e m_blend_func; + const BlendOp_e m_blend_op_rgb; + const CustomBlendFunc_e m_src_blend_func; + const CustomBlendFunc_e m_dst_blend_func; + const BlendOp_e m_blend_op_alpha; + const CustomBlendFunc_e m_src_blend_func_alpha; + const CustomBlendFunc_e m_dst_blend_func_alpha; + + BlendFuncParameters(const BlendFunc_e blendFunc, const BlendOp_e blend_Op_Rgb, const CustomBlendFunc_e src_Blend_Func, const CustomBlendFunc_e dst_Blend_Func, + const BlendOp_e blend_Op_Alpha, const CustomBlendFunc_e src_Blend_Func_Alpha, const CustomBlendFunc_e dst_Blend_Func_Alpha) + : m_blend_func(blendFunc), + m_blend_op_rgb(blend_Op_Rgb), + m_src_blend_func(src_Blend_Func), + m_dst_blend_func(dst_Blend_Func), + m_blend_op_alpha(blend_Op_Alpha), + m_src_blend_func_alpha(src_Blend_Func_Alpha), + m_dst_blend_func_alpha(dst_Blend_Func_Alpha) + { + } + }; + + BlendFuncParameters knownBlendFuncs[5] + { + BlendFuncParameters(BlendFunc_e::ADD, BlendOp_e::ADD, CustomBlendFunc_e::ONE, CustomBlendFunc_e::ONE, BlendOp_e::DISABLE, CustomBlendFunc_e::UNKNOWN, CustomBlendFunc_e::UNKNOWN), + BlendFuncParameters(BlendFunc_e::BLEND, BlendOp_e::ADD, CustomBlendFunc_e::SRC_ALPHA, CustomBlendFunc_e::INV_SRC_ALPHA, BlendOp_e::DISABLE, CustomBlendFunc_e::UNKNOWN, + CustomBlendFunc_e::UNKNOWN), + BlendFuncParameters(BlendFunc_e::MULTIPLY, BlendOp_e::ADD, CustomBlendFunc_e::ZERO, CustomBlendFunc_e::SRC_COLOR, BlendOp_e::DISABLE, CustomBlendFunc_e::UNKNOWN, + CustomBlendFunc_e::UNKNOWN), + BlendFuncParameters(BlendFunc_e::REPLACE, BlendOp_e::DISABLE, CustomBlendFunc_e::UNKNOWN, CustomBlendFunc_e::UNKNOWN, BlendOp_e::DISABLE, CustomBlendFunc_e::UNKNOWN, + CustomBlendFunc_e::UNKNOWN), + BlendFuncParameters(BlendFunc_e::SCREEN_ADD, BlendOp_e::ADD, CustomBlendFunc_e::INV_DST_COLOR, CustomBlendFunc_e::ONE, BlendOp_e::DISABLE, CustomBlendFunc_e::UNKNOWN, + CustomBlendFunc_e::UNKNOWN), + }; + + template + bool KnownBlendFuncParameterMatches(const T materialValue, const T blendFuncValue) + { + if (blendFuncValue == T::UNKNOWN) + return true; + if (materialValue == T::UNKNOWN) + return false; + + return static_cast(materialValue) == static_cast(blendFuncValue); + } + + void ExamineBlendFunc() + { + if (m_state_bits_info.m_blend_func != BlendFunc_e::UNKNOWN) + return; + + for (const auto& knownBlendFunc : knownBlendFuncs) + { + if (KnownBlendFuncParameterMatches(m_state_bits_info.m_custom_blend_op_rgb, knownBlendFunc.m_blend_op_rgb) + && KnownBlendFuncParameterMatches(m_state_bits_info.m_custom_src_blend_func, knownBlendFunc.m_src_blend_func) + && KnownBlendFuncParameterMatches(m_state_bits_info.m_custom_dst_blend_func, knownBlendFunc.m_dst_blend_func) + && KnownBlendFuncParameterMatches(m_state_bits_info.m_custom_blend_op_alpha, knownBlendFunc.m_blend_op_alpha) + && KnownBlendFuncParameterMatches(m_state_bits_info.m_custom_src_blend_func_alpha, knownBlendFunc.m_src_blend_func_alpha) + && KnownBlendFuncParameterMatches(m_state_bits_info.m_custom_dst_blend_func_alpha, knownBlendFunc.m_dst_blend_func_alpha) + ) + { + m_state_bits_info.m_blend_func = knownBlendFunc.m_blend_func; + return; + } + } + + m_state_bits_info.m_blend_func = BlendFunc_e::CUSTOM; + } + template T StateBitsToEnum(const unsigned input, const size_t mask, const size_t shift) { @@ -991,6 +1071,35 @@ namespace IW4 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; + + if (m_state_bits_info.m_gamma_write == StateBitsEnabledStatus_e::UNKNOWN) + m_state_bits_info.m_gamma_write = (stateBits.loadBits[0] & GFXS0_GAMMAWRITE) ? StateBitsEnabledStatus_e::ENABLED : StateBitsEnabledStatus_e::DISABLED; + + if (m_state_bits_info.m_stencil_front_func == StencilFunc_e::UNKNOWN) + m_state_bits_info.m_stencil_front_func = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_FRONT_FUNC_MASK, GFXS1_STENCIL_FRONT_FUNC_SHIFT); + + if (m_state_bits_info.m_stencil_front_pass == StencilOp_e::UNKNOWN) + m_state_bits_info.m_stencil_front_pass = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_FRONT_PASS_MASK, GFXS1_STENCIL_FRONT_PASS_SHIFT); + + if (m_state_bits_info.m_stencil_front_fail == StencilOp_e::UNKNOWN) + m_state_bits_info.m_stencil_front_fail = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_FRONT_FAIL_MASK, GFXS1_STENCIL_FRONT_FAIL_SHIFT); + + if (m_state_bits_info.m_stencil_front_zfail == StencilOp_e::UNKNOWN) + m_state_bits_info.m_stencil_front_zfail = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_FRONT_ZFAIL_MASK, GFXS1_STENCIL_FRONT_ZFAIL_SHIFT); + + if (m_state_bits_info.m_stencil_back_func == StencilFunc_e::UNKNOWN) + m_state_bits_info.m_stencil_back_func = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_BACK_FUNC_MASK, GFXS1_STENCIL_BACK_FUNC_SHIFT); + + if (m_state_bits_info.m_stencil_back_pass == StencilOp_e::UNKNOWN) + m_state_bits_info.m_stencil_back_pass = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_BACK_PASS_MASK, GFXS1_STENCIL_BACK_PASS_SHIFT); + + if (m_state_bits_info.m_stencil_back_fail == StencilOp_e::UNKNOWN) + m_state_bits_info.m_stencil_back_fail = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_BACK_FAIL_MASK, GFXS1_STENCIL_BACK_FAIL_SHIFT); + + if (m_state_bits_info.m_stencil_back_zfail == StencilOp_e::UNKNOWN) + m_state_bits_info.m_stencil_back_zfail = StateBitsToEnum(stateBits.loadBits[1], GFXS1_STENCIL_BACK_ZFAIL_MASK, GFXS1_STENCIL_BACK_ZFAIL_SHIFT); + + ExamineBlendFunc(); } void SetMaterialTypeValues() @@ -1027,6 +1136,15 @@ namespace IW4 SetValue("colorWriteGreen", GdtStateBitsEnabledStatusNames[static_cast(m_state_bits_info.m_color_write_rgb)]); SetValue("colorWriteBlue", GdtStateBitsEnabledStatusNames[static_cast(m_state_bits_info.m_color_write_rgb)]); SetValue("colorWriteAlpha", GdtStateBitsEnabledStatusNames[static_cast(m_state_bits_info.m_color_write_alpha)]); + SetValue("gammaWrite", GdtStateBitsOnOffStatusNames[static_cast(m_state_bits_info.m_gamma_write)]); + SetValue("stencilFunc1", GdtStencilFuncNames[static_cast(m_state_bits_info.m_stencil_front_func)]); + SetValue("stencilOpPass1", GdtStencilOpNames[static_cast(m_state_bits_info.m_stencil_front_pass)]); + SetValue("stencilOpFail1", GdtStencilOpNames[static_cast(m_state_bits_info.m_stencil_front_fail)]); + SetValue("stencilOpZFail1", GdtStencilOpNames[static_cast(m_state_bits_info.m_stencil_front_zfail)]); + SetValue("stencilFunc2", GdtStencilFuncNames[static_cast(m_state_bits_info.m_stencil_back_func)]); + SetValue("stencilOpPass2", GdtStencilOpNames[static_cast(m_state_bits_info.m_stencil_back_pass)]); + SetValue("stencilOpFail2", GdtStencilOpNames[static_cast(m_state_bits_info.m_stencil_back_fail)]); + SetValue("stencilOpZFail2", GdtStencilOpNames[static_cast(m_state_bits_info.m_stencil_back_zfail)]); } void SetTextureTableValues()