From 5771044c08f2aad82743a2dfc0e0d05ca6d5b552 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 6 Aug 2022 10:52:52 +0200 Subject: [PATCH] Material dumping and loading stuff --- src/Common/Game/IW3/IW3_Assets.h | 271 ++++++++++++++++++ src/Common/Game/IW4/IW4_Assets.h | 4 + src/ObjCommon/Game/IW4/MaterialConstantsIW4.h | 91 +++--- .../IW4/AssetLoaders/AssetLoaderMaterial.cpp | 146 +++++++++- .../IW4/AssetDumpers/AssetDumperMaterial.cpp | 37 ++- 5 files changed, 510 insertions(+), 39 deletions(-) diff --git a/src/Common/Game/IW3/IW3_Assets.h b/src/Common/Game/IW3/IW3_Assets.h index efb48b54..af8782ef 100644 --- a/src/Common/Game/IW3/IW3_Assets.h +++ b/src/Common/Game/IW3/IW3_Assets.h @@ -775,6 +775,15 @@ namespace IW3 uint16_t hashIndex; }; + enum GfxCameraRegionType + { + CAMERA_REGION_LIT = 0x0, + CAMERA_REGION_DECAL = 0x1, + CAMERA_REGION_EMISSIVE = 0x2, + CAMERA_REGION_COUNT = 0x3, + CAMERA_REGION_NONE = 0x3, + }; + struct Material { MaterialInfo info; @@ -810,17 +819,279 @@ namespace IW3 MTL_ARG_MATERIAL_VERTEX_CONST = 0x0, MTL_ARG_LITERAL_VERTEX_CONST = 0x1, MTL_ARG_MATERIAL_PIXEL_SAMPLER = 0x2, + MTL_ARG_CODE_PRIM_BEGIN = 0x3, + MTL_ARG_CODE_VERTEX_CONST = 0x3, MTL_ARG_CODE_PIXEL_SAMPLER = 0x4, MTL_ARG_CODE_PIXEL_CONST = 0x5, + MTL_ARG_CODE_PRIM_END = 0x6, + MTL_ARG_MATERIAL_PIXEL_CONST = 0x6, MTL_ARG_LITERAL_PIXEL_CONST = 0x7, MLT_ARG_COUNT }; + enum MaterialConstantSource + { + CONST_SRC_CODE_MAYBE_DIRTY_PS_BEGIN = 0x0, + CONST_SRC_CODE_LIGHT_POSITION = 0x0, + CONST_SRC_CODE_LIGHT_DIFFUSE = 0x1, + CONST_SRC_CODE_LIGHT_SPOTDIR = 0x2, + CONST_SRC_CODE_LIGHT_SPOTFACTORS = 0x3, + CONST_SRC_CODE_LIGHT_ATTENUATION = 0x4, + CONST_SRC_CODE_LIGHT_FALLOFF_A = 0x5, + CONST_SRC_CODE_LIGHT_FALLOFF_B = 0x6, + CONST_SRC_CODE_LIGHT_SPOT_MATRIX0 = 0x7, + CONST_SRC_CODE_LIGHT_SPOT_MATRIX1 = 0x8, + CONST_SRC_CODE_LIGHT_SPOT_MATRIX2 = 0x9, + CONST_SRC_CODE_LIGHT_SPOT_MATRIX3 = 0xA, + CONST_SRC_CODE_LIGHT_SPOT_AABB = 0xB, + CONST_SRC_CODE_LIGHT_CONE_CONTROL1 = 0xC, + CONST_SRC_CODE_LIGHT_CONE_CONTROL2 = 0xD, + CONST_SRC_CODE_LIGHT_SPOT_COOKIE_SLIDE_CONTROL = 0xE, + CONST_SRC_CODE_SHADOW_PARMS = 0xF, + CONST_SRC_CODE_SHADOWMAP_POLYGON_OFFSET = 0x10, + CONST_SRC_CODE_RENDER_TARGET_SIZE = 0x11, + CONST_SRC_CODE_UPSCALED_TARGET_SIZE = 0x12, + CONST_SRC_CODE_DOF_EQUATION_VIEWMODEL_AND_FAR_BLUR = 0x13, + CONST_SRC_CODE_DOF_EQUATION_SCENE = 0x14, + CONST_SRC_CODE_DOF_LERP_SCALE = 0x15, + CONST_SRC_CODE_DOF_LERP_BIAS = 0x16, + CONST_SRC_CODE_DOF_ROW_DELTA = 0x17, + CONST_SRC_CODE_PARTICLE_CLOUD_COLOR = 0x18, + CONST_SRC_CODE_GAMETIME = 0x19, + CONST_SRC_CODE_MAYBE_DIRTY_PS_END = 0x1A, + CONST_SRC_CODE_ALWAYS_DIRTY_PS_BEGIN = 0x1A, + CONST_SRC_CODE_FILTER_TAP_0 = 0x1A, + CONST_SRC_CODE_FILTER_TAP_1 = 0x1B, + CONST_SRC_CODE_FILTER_TAP_2 = 0x1C, + CONST_SRC_CODE_FILTER_TAP_3 = 0x1D, + CONST_SRC_CODE_FILTER_TAP_4 = 0x1E, + CONST_SRC_CODE_FILTER_TAP_5 = 0x1F, + CONST_SRC_CODE_FILTER_TAP_6 = 0x20, + CONST_SRC_CODE_FILTER_TAP_7 = 0x21, + CONST_SRC_CODE_COLOR_MATRIX_R = 0x22, + CONST_SRC_CODE_COLOR_MATRIX_G = 0x23, + CONST_SRC_CODE_COLOR_MATRIX_B = 0x24, + CONST_SRC_CODE_ALWAYS_DIRTY_PS_END = 0x25, + CONST_SRC_CODE_NEVER_DIRTY_PS_BEGIN = 0x25, + CONST_SRC_CODE_SHADOWMAP_SWITCH_PARTITION = 0x25, + CONST_SRC_CODE_SUNSHADOWMAP_PIXEL_SIZE = 0x26, + CONST_SRC_CODE_SHADOWMAP_SCALE = 0x27, + CONST_SRC_CODE_ZNEAR = 0x28, + CONST_SRC_CODE_SUN_POSITION = 0x29, + CONST_SRC_CODE_SUN_DIFFUSE = 0x2A, + CONST_SRC_CODE_LIGHTING_LOOKUP_SCALE = 0x2B, + CONST_SRC_CODE_DEBUG_BUMPMAP = 0x2C, + CONST_SRC_CODE_DEBUG_PERFORMANCE = 0x2D, + CONST_SRC_CODE_MATERIAL_COLOR = 0x2E, + CONST_SRC_CODE_FOG = 0x2F, + CONST_SRC_CODE_FOG2 = 0x30, + CONST_SRC_CODE_FOG_COLOR = 0x31, + CONST_SRC_CODE_SUN_FOG = 0x32, + CONST_SRC_CODE_SUN_FOG_DIR = 0x33, + CONST_SRC_CODE_SUN_FOG_COLOR = 0x34, + CONST_SRC_CODE_GLOW_SETUP = 0x35, + CONST_SRC_CODE_GLOW_APPLY = 0x36, + CONST_SRC_CODE_COLOR_BIAS = 0x37, + CONST_SRC_CODE_COLOR_TINT_BASE = 0x38, + CONST_SRC_CODE_COLOR_TINT_DELTA = 0x39, + CONST_SRC_CODE_OUTDOOR_FEATHER_PARMS = 0x3A, + CONST_SRC_CODE_SKY_TRANSITION = 0x3B, + CONST_SRC_CODE_SPOT_SHADOWMAP_PIXEL_ADJUST = 0x3C, + CONST_SRC_CODE_DLIGHT_SPOT_SHADOWMAP_PIXEL_ADJUST = 0x3D, + CONST_SRC_CODE_CLIP_SPACE_LOOKUP_SCALE = 0x3E, + CONST_SRC_CODE_CLIP_SPACE_LOOKUP_OFFSET = 0x3F, + CONST_SRC_CODE_PARTICLE_CLOUD_MATRIX = 0x40, + CONST_SRC_CODE_PARTICLE_CLOUD_VEL_WORLD = 0x41, + CONST_SRC_CODE_DEPTH_FROM_CLIP = 0x42, + CONST_SRC_CODE_CODE_MESH_ARG_0 = 0x43, + CONST_SRC_CODE_CODE_MESH_ARG_1 = 0x44, + CONST_SRC_CODE_CODE_MESH_ARG_LAST = 0x44, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS = 0x45, + CONST_SRC_CODE_GRID_LIGHTING_SH_0 = 0x46, + CONST_SRC_CODE_GRID_LIGHTING_SH_1 = 0x47, + CONST_SRC_CODE_GRID_LIGHTING_SH_2 = 0x48, + CONST_SRC_CODE_REFLECTION_LIGHTING_SH_0 = 0x49, + CONST_SRC_CODE_REFLECTION_LIGHTING_SH_1 = 0x4A, + CONST_SRC_CODE_REFLECTION_LIGHTING_SH_2 = 0x4B, + CONST_SRC_CODE_WIND_DIRECTION = 0x4C, + CONST_SRC_CODE_MOTIONBLUR_DIRECTION_AND_MAGNITUDE = 0x4D, + CONST_SRC_CODE_COMPOSITE_FX_DISTORTION = 0x4E, + CONST_SRC_CODE_GLOW_BLOOM_SCALE = 0x4F, + CONST_SRC_CODE_COMPOSITE_FX_OVERLAY_TEXCOORD = 0x50, + CONST_SRC_CODE_COLOR_BIAS1 = 0x51, + CONST_SRC_CODE_COLOR_TINT_BASE1 = 0x52, + CONST_SRC_CODE_COLOR_TINT_DELTA1 = 0x53, + CONST_SRC_CODE_POSTFX_FADE_EFFECT = 0x54, + CONST_SRC_CODE_VIEWPORT_DIMENSIONS = 0x55, + CONST_SRC_CODE_FRAMEBUFFER_READ = 0x56, + CONST_SRC_CODE_RESIZE_PARAMS1 = 0x57, + CONST_SRC_CODE_RESIZE_PARAMS2 = 0x58, + CONST_SRC_CODE_RESIZE_PARAMS3 = 0x59, + CONST_SRC_CODE_VARIANT_WIND_SPRING_0 = 0x5A, + CONST_SRC_CODE_VARIANT_WIND_SPRING_1 = 0x5B, + CONST_SRC_CODE_VARIANT_WIND_SPRING_2 = 0x5C, + CONST_SRC_CODE_VARIANT_WIND_SPRING_3 = 0x5D, + CONST_SRC_CODE_VARIANT_WIND_SPRING_4 = 0x5E, + CONST_SRC_CODE_VARIANT_WIND_SPRING_5 = 0x5F, + CONST_SRC_CODE_VARIANT_WIND_SPRING_6 = 0x60, + CONST_SRC_CODE_VARIANT_WIND_SPRING_7 = 0x61, + CONST_SRC_CODE_VARIANT_WIND_SPRING_8 = 0x62, + CONST_SRC_CODE_VARIANT_WIND_SPRING_9 = 0x63, + CONST_SRC_CODE_VARIANT_WIND_SPRING_10 = 0x64, + CONST_SRC_CODE_VARIANT_WIND_SPRING_11 = 0x65, + CONST_SRC_CODE_VARIANT_WIND_SPRING_12 = 0x66, + CONST_SRC_CODE_VARIANT_WIND_SPRING_13 = 0x67, + CONST_SRC_CODE_VARIANT_WIND_SPRING_14 = 0x68, + CONST_SRC_CODE_VARIANT_WIND_SPRING_15 = 0x69, + CONST_SRC_CODE_CHARACTER_CHARRED_AMOUNT = 0x6A, + CONST_SRC_CODE_POSTFX_CONTROL0 = 0x6B, + CONST_SRC_CODE_POSTFX_CONTROL1 = 0x6C, + CONST_SRC_CODE_POSTFX_CONTROL2 = 0x6D, + CONST_SRC_CODE_POSTFX_CONTROL3 = 0x6E, + CONST_SRC_CODE_POSTFX_CONTROL4 = 0x6F, + CONST_SRC_CODE_POSTFX_CONTROL5 = 0x70, + CONST_SRC_CODE_POSTFX_CONTROL6 = 0x71, + CONST_SRC_CODE_POSTFX_CONTROL7 = 0x72, + CONST_SRC_CODE_POSTFX_CONTROL8 = 0x73, + CONST_SRC_CODE_POSTFX_CONTROL9 = 0x74, + CONST_SRC_CODE_POSTFX_CONTROLA = 0x75, + CONST_SRC_CODE_POSTFX_CONTROLB = 0x76, + CONST_SRC_CODE_POSTFX_CONTROLC = 0x77, + CONST_SRC_CODE_POSTFX_CONTROLD = 0x78, + CONST_SRC_CODE_POSTFX_CONTROLE = 0x79, + CONST_SRC_CODE_POSTFX_CONTROLF = 0x7A, + CONST_SRC_CODE_HDRCONTROL_0 = 0x7B, + CONST_SRC_CODE_HDRCONTROL_1 = 0x7C, + CONST_SRC_CODE_GLIGHT_POSXS = 0x7D, + CONST_SRC_CODE_GLIGHT_POSYS = 0x7E, + CONST_SRC_CODE_GLIGHT_POSZS = 0x7F, + CONST_SRC_CODE_GLIGHT_FALLOFFS = 0x80, + CONST_SRC_CODE_GLIGHT_REDS = 0x81, + CONST_SRC_CODE_GLIGHT_GREENS = 0x82, + CONST_SRC_CODE_GLIGHT_BLUES = 0x83, + CONST_SRC_CODE_DLIGHT_POSITION = 0x84, + CONST_SRC_CODE_DLIGHT_DIFFUSE = 0x85, + CONST_SRC_CODE_DLIGHT_ATTENUATION = 0x86, + CONST_SRC_CODE_DLIGHT_FALLOFF = 0x87, + CONST_SRC_CODE_DLIGHT_SPOT_MATRIX_0 = 0x88, + CONST_SRC_CODE_DLIGHT_SPOT_MATRIX_1 = 0x89, + CONST_SRC_CODE_DLIGHT_SPOT_MATRIX_2 = 0x8A, + CONST_SRC_CODE_DLIGHT_SPOT_MATRIX_3 = 0x8B, + CONST_SRC_CODE_DLIGHT_SPOT_DIR = 0x8C, + CONST_SRC_CODE_DLIGHT_SPOT_FACTORS = 0x8D, + CONST_SRC_CODE_DLIGHT_SHADOW_LOOKUP_MATRIX_0 = 0x8E, + CONST_SRC_CODE_DLIGHT_SHADOW_LOOKUP_MATRIX_1 = 0x8F, + CONST_SRC_CODE_DLIGHT_SHADOW_LOOKUP_MATRIX_2 = 0x90, + CONST_SRC_CODE_DLIGHT_SHADOW_LOOKUP_MATRIX_3 = 0x91, + CONST_SRC_CODE_CLOUD_LAYER_CONTROL0 = 0x92, + CONST_SRC_CODE_CLOUD_LAYER_CONTROL1 = 0x93, + CONST_SRC_CODE_CLOUD_LAYER_CONTROL2 = 0x94, + CONST_SRC_CODE_CLOUD_LAYER_CONTROL3 = 0x95, + CONST_SRC_CODE_CLOUD_LAYER_CONTROL4 = 0x96, + CONST_SRC_CODE_HERO_LIGHTING_R = 0x97, + CONST_SRC_CODE_HERO_LIGHTING_G = 0x98, + CONST_SRC_CODE_HERO_LIGHTING_B = 0x99, + CONST_SRC_CODE_LIGHT_HERO_SCALE = 0x9A, + CONST_SRC_CODE_CINEMATIC_BLUR_BOX = 0x9B, + CONST_SRC_CODE_CINEMATIC_BLUR_BOX2 = 0x9C, + CONST_SRC_CODE_ADSZSCALE = 0x9D, + CONST_SRC_CODE_UI3D_UV_SETUP_0 = 0x9E, + CONST_SRC_CODE_UI3D_UV_SETUP_1 = 0x9F, + CONST_SRC_CODE_UI3D_UV_SETUP_2 = 0xA0, + CONST_SRC_CODE_UI3D_UV_SETUP_3 = 0xA1, + CONST_SRC_CODE_UI3D_UV_SETUP_4 = 0xA2, + CONST_SRC_CODE_UI3D_UV_SETUP_5 = 0xA3, + CONST_SRC_CODE_CHARACTER_DISSOLVE_COLOR = 0xA4, + CONST_SRC_CODE_CAMERA_LOOK = 0xA5, + CONST_SRC_CODE_CAMERA_UP = 0xA6, + CONST_SRC_CODE_CAMERA_SIDE = 0xA7, + CONST_SRC_CODE_RIMINTENSITY = 0xA8, + CONST_SRC_CODE_GENERIC_PARAM0 = 0xA9, + CONST_SRC_CODE_GENERIC_PARAM1 = 0xAA, + CONST_SRC_CODE_GENERIC_PARAM2 = 0xAB, + CONST_SRC_CODE_GENERIC_PARAM3 = 0xAC, + CONST_SRC_CODE_GENERIC_PARAM4 = 0xAD, + CONST_SRC_CODE_GENERIC_PARAM5 = 0xAE, + CONST_SRC_CODE_GENERIC_PARAM6 = 0xAF, + CONST_SRC_CODE_GENERIC_PARAM7 = 0xB0, + CONST_SRC_CODE_GENERIC_EYEOFFSET = 0xB1, + CONST_SRC_CODE_GENERIC_QUADINTENSITY = 0xB2, + CONST_SRC_CODE_WEAPON_PARAM0 = 0xB3, + CONST_SRC_CODE_WEAPON_PARAM1 = 0xB4, + CONST_SRC_CODE_WEAPON_PARAM2 = 0xB5, + CONST_SRC_CODE_WEAPON_PARAM3 = 0xB6, + CONST_SRC_CODE_WEAPON_PARAM4 = 0xB7, + CONST_SRC_CODE_WEAPON_PARAM5 = 0xB8, + CONST_SRC_CODE_WEAPON_PARAM6 = 0xB9, + CONST_SRC_CODE_WEAPON_PARAM7 = 0xBA, + CONST_SRC_CODE_WEAPON_PARAM8 = 0xBB, + CONST_SRC_CODE_WEAPON_PARAM9 = 0xBC, + CONST_SRC_CODE_QRCODE_0 = 0xBD, + CONST_SRC_CODE_QRCODE_1 = 0xBE, + CONST_SRC_CODE_QRCODE_2 = 0xBF, + CONST_SRC_CODE_QRCODE_3 = 0xC0, + CONST_SRC_CODE_QRCODE_4 = 0xC1, + CONST_SRC_CODE_QRCODE_5 = 0xC2, + CONST_SRC_CODE_QRCODE_6 = 0xC3, + CONST_SRC_CODE_QRCODE_7 = 0xC4, + CONST_SRC_CODE_QRCODE_8 = 0xC5, + CONST_SRC_CODE_QRCODE_9 = 0xC6, + CONST_SRC_CODE_QRCODE_10 = 0xC7, + CONST_SRC_CODE_QRCODE_11 = 0xC8, + CONST_SRC_CODE_EYEOFFSET = 0xC9, + CONST_SRC_CODE_SKY_COLOR_MULTIPLIER = 0xCA, + CONST_SRC_CODE_EXTRA_CAM_PARAM = 0xCB, + CONST_SRC_CODE_EMBLEM_LUT_SELECTOR = 0xCC, + CONST_SRC_CODE_DEBUG_COLOR_OVERRIDE = 0xCD, + CONST_SRC_CODE_DEBUG_ALPHA_OVERRIDE = 0xCE, + CONST_SRC_CODE_DEBUG_NORMAL_OVERRIDE = 0xCF, + CONST_SRC_CODE_DEBUG_SPECULAR_OVERRIDE = 0xD0, + CONST_SRC_CODE_DEBUG_GLOSS_OVERRIDE = 0xD1, + CONST_SRC_CODE_DEBUG_OCCLUSION_OVERRIDE = 0xD2, + CONST_SRC_CODE_NEVER_DIRTY_PS_END = 0xD3, + CONST_SRC_CODE_COUNT_FLOAT4 = 0xD3, + CONST_SRC_FIRST_CODE_MATRIX = 0xD3, + CONST_SRC_CODE_WORLD_MATRIX = 0xD3, + CONST_SRC_CODE_INVERSE_WORLD_MATRIX = 0xD4, + CONST_SRC_CODE_TRANSPOSE_WORLD_MATRIX = 0xD5, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_MATRIX = 0xD6, + CONST_SRC_CODE_VIEW_MATRIX = 0xD7, + CONST_SRC_CODE_INVERSE_VIEW_MATRIX = 0xD8, + CONST_SRC_CODE_TRANSPOSE_VIEW_MATRIX = 0xD9, + CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_MATRIX = 0xDA, + CONST_SRC_CODE_PROJECTION_MATRIX = 0xDB, + CONST_SRC_CODE_INVERSE_PROJECTION_MATRIX = 0xDC, + CONST_SRC_CODE_TRANSPOSE_PROJECTION_MATRIX = 0xDD, + CONST_SRC_CODE_INVERSE_TRANSPOSE_PROJECTION_MATRIX = 0xDE, + CONST_SRC_CODE_WORLD_VIEW_MATRIX = 0xDF, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_MATRIX = 0xE0, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_MATRIX = 0xE1, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX = 0xE2, + CONST_SRC_CODE_VIEW_PROJECTION_MATRIX = 0xE3, + CONST_SRC_CODE_INVERSE_VIEW_PROJECTION_MATRIX = 0xE4, + CONST_SRC_CODE_TRANSPOSE_VIEW_PROJECTION_MATRIX = 0xE5, + CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_PROJECTION_MATRIX = 0xE6, + CONST_SRC_CODE_WORLD_VIEW_PROJECTION_MATRIX = 0xE7, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_PROJECTION_MATRIX = 0xE8, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX = 0xE9, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX = 0xEA, + CONST_SRC_CODE_SHADOW_LOOKUP_MATRIX = 0xEB, + CONST_SRC_CODE_INVERSE_SHADOW_LOOKUP_MATRIX = 0xEC, + CONST_SRC_CODE_TRANSPOSE_SHADOW_LOOKUP_MATRIX = 0xED, + CONST_SRC_CODE_INVERSE_TRANSPOSE_SHADOW_LOOKUP_MATRIX = 0xEE, + CONST_SRC_CODE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0xEF, + CONST_SRC_CODE_INVERSE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0xF0, + CONST_SRC_CODE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0xF1, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0xF2, + CONST_SRC_TOTAL_COUNT = 0xF3, + CONST_SRC_NONE = 0xF4, + }; + struct MaterialShaderArgument { uint16_t type; diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index 2e54ae8d..2802a86b 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -1461,7 +1461,9 @@ namespace IW4 TECHNIQUE_EMISSIVE_DFOG = 0x6, TECHNIQUE_EMISSIVE_SHADOW = 0x7, TECHNIQUE_EMISSIVE_SHADOW_DFOG = 0x8, + TECHNIQUE_LIT_BEGIN = 0x9, + TECHNIQUE_LIT = 0x9, TECHNIQUE_LIT_DFOG = 0xA, TECHNIQUE_LIT_SUN = 0xB, @@ -1490,7 +1492,9 @@ namespace IW4 TECHNIQUE_LIT_INSTANCED_OMNI_DFOG = 0x22, TECHNIQUE_LIT_INSTANCED_OMNI_SHADOW = 0x23, TECHNIQUE_LIT_INSTANCED_OMNI_SHADOW_DFOG = 0x24, + TECHNIQUE_LIT_END = 0x25, + TECHNIQUE_LIGHT_SPOT = 0x25, TECHNIQUE_LIGHT_OMNI = 0x26, TECHNIQUE_LIGHT_SPOT_SHADOW = 0x27, diff --git a/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h b/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h index 01021bb8..66f81797 100644 --- a/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h +++ b/src/ObjCommon/Game/IW4/MaterialConstantsIW4.h @@ -326,6 +326,31 @@ namespace IW4 }; static_assert(std::extent_v == static_cast(PolygonOffset_e::COUNT)); + enum class StencilIndex + { + FRONT, + BACK + }; + + enum class StencilMode_e + { + UNKNOWN, + DISABLED, + ONE_SIDED, + TWO_SIDED, + + COUNT + }; + + inline const char* GdtStencilModeNames[] + { + "", + "Disable", + "One-sided", + "Two-sided" + }; + static_assert(std::extent_v == static_cast(StencilMode_e::COUNT)); + enum class StencilFunc_e { UNKNOWN, @@ -476,8 +501,8 @@ namespace IW4 GDT_SORTKEY_OPAQUE, // 1 GDT_SORTKEY_SKY, // 2 GDT_SORTKEY_SKYBOX, // 3 - "?", // 4 - "?", // 5 + nullptr, // ? 4 + nullptr, // ? 5 GDT_SORTKEY_DECAL_BOTTOM_1, // 6 GDT_SORTKEY_DECAL_BOTTOM_2, // 7 GDT_SORTKEY_DECAL_BOTTOM_3, // 8 @@ -486,45 +511,45 @@ namespace IW4 GDT_SORTKEY_DECAL_MIDDLE_2, // 11 GDT_SORTKEY_DECAL_MIDDLE_3, // 12 GDT_SORTKEY_DECAL_WEAPON_IMPACT, // 13 - "?", // 14 - "?", // 15 - "?", // 16 - "?", // 17 - "?", // 18 - "?", // 19 - "?", // 20 - "?", // 21 - "-", // 22 - "-", // 23 + nullptr, // ? 14 + nullptr, // ? 15 + nullptr, // ? 16 + nullptr, // ? 17 + nullptr, // ? 18 + nullptr, // ? 19 + nullptr, // ? 20 + nullptr, // ? 21 + nullptr, // - 22 + nullptr, // - 23 GDT_SORTKEY_WINDOW_INSIDE, // 24 GDT_SORTKEY_WINDOW_OUTSIDE, // 25 - "?", // 26 - "?", // 27 - "?", // 28 - "?", // 29 - "?", // 30 - "?", // 31 - "?", // 32 - "?", // 33 - "?", // 34 - "?", // 35 - "?", // 36 - "?", // 37 - "?", // 38 - "?", // 39 - "?", // 40 - "?", // 41 - "?", // 42 + nullptr, // ? 26 + nullptr, // ? 27 + nullptr, // ? 28 + nullptr, // ? 29 + nullptr, // ? 30 + nullptr, // ? 31 + nullptr, // ? 32 + nullptr, // ? 33 + nullptr, // ? 34 + nullptr, // ? 35 + nullptr, // ? 36 + nullptr, // ? 37 + nullptr, // ? 38 + nullptr, // ? 39 + nullptr, // ? 40 + nullptr, // ? 41 + nullptr, // ? 42 GDT_SORTKEY_DISTORTION, // 43 - "?", // 44 - "?", // 45 - "-", // 46 + nullptr, // ? 44 + nullptr, // ? 45 + nullptr, // - 46 GDT_SORTKEY_BLEND_ADDITIVE, // 47 GDT_SORTKEY_EFFECT_AUTO_SORT, // 48 GDT_SORTKEY_AFTER_EFFECT_BOTTOM, // 49 GDT_SORTKEY_AFTER_EFFECT_MIDDLE, // 50 GDT_SORTKEY_AFTER_EFFECT_TOP, // 51 - "-", // 52 + nullptr, // - 52 GDT_SORTKEY_VIEWMODEL_EFFECT, // 53 }; static_assert(std::extent_v == static_cast(SORTKEY_MAX)); diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp index 04c4a47f..aa52187b 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp @@ -310,7 +310,7 @@ namespace IW4 bool foundSortKey = false; for (auto sortKeyIndex = 0u; sortKeyIndex < SORTKEY_MAX; sortKeyIndex++) { - if (sortKey == SortKeyNames[sortKeyIndex]) + if (SortKeyNames[sortKeyIndex] && sortKey == SortKeyNames[sortKeyIndex]) { SetSort(static_cast(sortKeyIndex)); foundSortKey = true; @@ -354,6 +354,7 @@ namespace IW4 cullface_template(); depthtest_template(); depthwrite_template(); + gammawrite_template(); polygonoffset_template(); stencil_template(); } @@ -449,7 +450,7 @@ namespace IW4 void depthwrite_template() { - const auto depthWrite = ReadEnumProperty("depthWrite", GdtStateBitsEnabledStatusNames, std::extent_v); + const auto depthWrite = ReadEnumProperty("depthWrite", GdtStateBitsOnOffStatusNames, std::extent_v); const auto blendFunc = ReadStringProperty("blendFunc"); if (depthWrite == StateBitsEnabledStatus_e::ENABLED) @@ -476,6 +477,20 @@ namespace IW4 } } + void gammawrite_template() + { + const auto gammaWrite = ReadEnumProperty("gammaWrite", GdtStateBitsOnOffStatusNames, std::extent_v); + + if (gammaWrite == StateBitsEnabledStatus_e::UNKNOWN) + { + std::ostringstream ss; + ss << "Invalid gammaWrite blendFunc value: \"\""; + throw GdtReadingException(ss.str()); + } + + SetGammaWrite(gammaWrite == StateBitsEnabledStatus_e::ENABLED); + } + void polygonoffset_template() { const auto polygonOffset = ReadEnumProperty("polygonOffset", GdtPolygonOffsetNames, std::extent_v); @@ -485,6 +500,32 @@ namespace IW4 void stencil_template() { + const auto stencilMode = ReadEnumProperty("stencil", GdtStencilModeNames, std::extent_v); + + if (stencilMode == StencilMode_e::DISABLED) + { + DisableStencil(StencilIndex::FRONT); + DisableStencil(StencilIndex::BACK); + } + else + { + if (stencilMode == StencilMode_e::TWO_SIDED) + { + const auto stencilBackFunc = ReadEnumProperty("stencilFunc2", GdtStencilFuncNames, std::extent_v); + const auto stencilBackOpFail = ReadEnumProperty("stencilOpFail2", GdtStencilOpNames, std::extent_v); + const auto stencilBackOpZFail = ReadEnumProperty("stencilOpZFail2", GdtStencilOpNames, std::extent_v); + const auto stencilBackOpPass = ReadEnumProperty("stencilOpPass2", GdtStencilOpNames, std::extent_v); + + EnableStencil(StencilIndex::BACK, stencilBackFunc, stencilBackOpFail, stencilBackOpZFail, stencilBackOpPass); + } + + const auto stencilFrontFunc = ReadEnumProperty("stencilFunc1", GdtStencilFuncNames, std::extent_v); + const auto stencilFrontOpFail = ReadEnumProperty("stencilOpFail1", GdtStencilOpNames, std::extent_v); + const auto stencilFrontOpZFail = ReadEnumProperty("stencilOpZFail1", GdtStencilOpNames, std::extent_v); + const auto stencilFrontOpPass = ReadEnumProperty("stencilOpPass1", GdtStencilOpNames, std::extent_v); + + EnableStencil(StencilIndex::FRONT, stencilFrontFunc, stencilFrontOpFail, stencilFrontOpZFail, stencilFrontOpPass); + } } void SetTechniqueSet(const std::string& techsetName) @@ -500,6 +541,39 @@ namespace IW4 m_dependencies.push_back(techset); m_material->techniqueSet = techset->Asset(); + + for (auto i = 0; i < TECHNIQUE_COUNT; i++) + { + if (m_material->techniqueSet->techniques[i]) + { + const auto stateBitsForTechnique = GetStateBitsForTechnique(static_cast(i)); + const auto foundStateBits = std::find_if(m_state_bits.begin(), m_state_bits.end(), + [stateBitsForTechnique](const GfxStateBits& s1) + { + return s1.loadBits[0] == stateBitsForTechnique.loadBits[0] && s1.loadBits[1] == stateBitsForTechnique.loadBits[1]; + }); + + if (foundStateBits != m_state_bits.end()) + { + m_material->stateBitsEntry[i] = static_cast(foundStateBits - m_state_bits.begin()); + } + else + { + m_material->stateBitsEntry[i] = static_cast(m_state_bits.size()); + m_state_bits.push_back(stateBitsForTechnique); + } + } + else + { + m_material->stateBitsEntry[i] = std::numeric_limits::max(); + } + } + } + + GfxStateBits GetStateBitsForTechnique(MaterialTechniqueType techniqueType) + { + // TODO: Use technique statemap to evaluate actual statebits + return m_base_statebits; } void AddMapTexture(const std::string& typeName, const TextureSemantic semantic, const std::string& textureName) @@ -696,6 +770,14 @@ namespace IW4 m_base_statebits.loadBits[1] |= GFXS1_DEPTHWRITE; } + void SetGammaWrite(const bool gammaWrite) + { + m_base_statebits.loadBits[0] &= ~GFXS0_GAMMAWRITE; + + if (gammaWrite) + m_base_statebits.loadBits[0] |= GFXS0_GAMMAWRITE; + } + void SetPolygonOffset(const PolygonOffset_e polygonOffset) { if (polygonOffset == PolygonOffset_e::UNKNOWN) @@ -709,6 +791,65 @@ namespace IW4 m_base_statebits.loadBits[1] |= ((static_cast(polygonOffset) - 1) >> GFXS1_POLYGON_OFFSET_SHIFT) & GFXS1_POLYGON_OFFSET_MASK; } + static void GetStencilMasksForIndex(const StencilIndex stencil, unsigned& enabledMask, unsigned& funcShift, unsigned& funcMask, unsigned& opFailShift, unsigned& opFailMask, + unsigned& opZFailShift, unsigned& opZFailMask, unsigned& opPassShift, unsigned& opPassMask) + { + if (stencil == StencilIndex::FRONT) + { + enabledMask = GFXS1_STENCIL_FRONT_ENABLE; + funcShift = GFXS1_STENCIL_FRONT_FUNC_SHIFT; + funcMask = GFXS1_STENCIL_FRONT_FUNC_MASK; + opFailShift = GFXS1_STENCIL_FRONT_FAIL_SHIFT; + opFailMask = GFXS1_STENCIL_FRONT_FAIL_MASK; + opZFailShift = GFXS1_STENCIL_FRONT_ZFAIL_SHIFT; + opZFailMask = GFXS1_STENCIL_FRONT_ZFAIL_MASK; + opPassShift = GFXS1_STENCIL_FRONT_PASS_SHIFT; + opPassMask = GFXS1_STENCIL_FRONT_PASS_MASK; + } + else + { + assert(stencil == StencilIndex::BACK); + + enabledMask = GFXS1_STENCIL_BACK_ENABLE; + funcShift = GFXS1_STENCIL_BACK_FUNC_SHIFT; + funcMask = GFXS1_STENCIL_BACK_FUNC_MASK; + opFailShift = GFXS1_STENCIL_BACK_FAIL_SHIFT; + opFailMask = GFXS1_STENCIL_BACK_FAIL_MASK; + opZFailShift = GFXS1_STENCIL_BACK_ZFAIL_SHIFT; + opZFailMask = GFXS1_STENCIL_BACK_ZFAIL_MASK; + opPassShift = GFXS1_STENCIL_BACK_PASS_SHIFT; + opPassMask = GFXS1_STENCIL_BACK_PASS_MASK; + } + } + + void DisableStencil(const StencilIndex stencil) + { + unsigned enabledMask, funcShift, funcMask, opFailShift, opFailMask, opZFailShift, opZFailMask, opPassShift, opPassMask; + GetStencilMasksForIndex(stencil, enabledMask, funcShift, funcMask, opFailShift, opFailMask, opZFailShift, opZFailMask, opPassShift, opPassMask); + + m_base_statebits.loadBits[1] &= ~(enabledMask | funcMask | opFailMask | opZFailMask | opPassMask); + } + + void EnableStencil(const StencilIndex stencil, StencilFunc_e stencilFunc, StencilOp_e stencilOpFail, StencilOp_e stencilOpZFail, StencilOp_e stencilOpPass) + { + unsigned enabledMask, funcShift, funcMask, opFailShift, opFailMask, opZFailShift, opZFailMask, opPassShift, opPassMask; + GetStencilMasksForIndex(stencil, enabledMask, funcShift, funcMask, opFailShift, opFailMask, opZFailShift, opZFailMask, opPassShift, opPassMask); + + m_base_statebits.loadBits[1] |= enabledMask; + + m_base_statebits.loadBits[1] &= ~funcMask; + m_base_statebits.loadBits[1] |= ((static_cast(stencilFunc) - 1) >> funcShift) & funcMask; + + m_base_statebits.loadBits[1] &= ~opFailMask; + m_base_statebits.loadBits[1] |= ((static_cast(stencilOpFail) - 1) >> opFailShift) & opFailMask; + + m_base_statebits.loadBits[1] &= ~opZFailMask; + m_base_statebits.loadBits[1] |= ((static_cast(stencilOpZFail) - 1) >> opZFailShift) & opZFailMask; + + m_base_statebits.loadBits[1] &= ~opPassMask; + m_base_statebits.loadBits[1] |= ((static_cast(stencilOpPass) - 1) >> opPassShift) & opPassMask; + } + void FinalizeMaterial() const { if (!m_textures.empty()) @@ -749,6 +890,7 @@ namespace IW4 Material* m_material; GfxStateBits m_base_statebits; + std::vector m_state_bits; std::vector m_textures; }; } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp index 01600811..d954aa40 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp @@ -13,7 +13,7 @@ #include "Game/IW4/TechsetConstantsIW4.h" #include "Math/Vector.h" -//#define DUMP_AS_JSON 1 +#define DUMP_AS_JSON 1 //#define DUMP_AS_GDT 1 //#define FLAGS_DEBUG 1 @@ -429,7 +429,7 @@ namespace IW4 {"stateFlags", material->stateFlags}, #endif {"cameraRegion", ArrayEntry(cameraRegionNames, material->cameraRegion)}, - {"techniqueSet", material->techniqueSet && material->techniqueSet->name ? AssetName(material->techniqueSet->name) : nullptr}, + {"techniqueSet", material->techniqueSet && material->techniqueSet->name ? AssetName(material->techniqueSet->name) : json{}}, {"textureTable", BuildTextureTableJson(material->textureTable, material->textureCount)}, {"constantTable", BuildConstantTableJson(material->constantTable, material->constantCount)}, {"stateBitsTable", BuildStateBitsTableJson(material->stateBitsTable, material->stateBitsCount)} @@ -448,6 +448,7 @@ namespace IW4 GdtCustomMaterialTypes m_gdt_custom_material_type = CUSTOM_MATERIAL_TYPE_NONE; std::string m_gdt_custom_string; MaterialType m_engine_material_type = MTL_TYPE_DEFAULT; + std::string m_sort_key_name; bool m_no_cast_shadow = false; bool m_no_receive_dynamic_shadow = false; bool m_no_fog = false; @@ -490,6 +491,7 @@ namespace IW4 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; + StencilMode_e m_stencil_mode = StencilMode_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; @@ -820,6 +822,15 @@ namespace IW4 } } + if (m_material->info.sortKey < SORTKEY_MAX && SortKeyNames[m_material->info.sortKey]) + { + m_techset_info.m_sort_key_name = SortKeyNames[m_material->info.sortKey]; + } + else + { + m_techset_info.m_sort_key_name = std::to_string(m_material->info.sortKey); + } + if (m_techset_info.m_techset_base_name == "2d") { m_techset_info.m_gdt_material_type = MATERIAL_TYPE_2D; @@ -1072,6 +1083,24 @@ namespace IW4 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_mode == StencilMode_e::UNKNOWN) + { + if ((stateBits.loadBits[1] & GFXS1_STENCIL_BACK_ENABLE) == 0 && (stateBits.loadBits[1] & GFXS1_STENCIL_FRONT_ENABLE) == 0) + { + m_state_bits_info.m_stencil_mode = StencilMode_e::DISABLED; + } + else if (stateBits.loadBits[1] & GFXS1_STENCIL_BACK_ENABLE) + { + assert(stateBits.loadBits[1] & GFXS1_STENCIL_FRONT_ENABLE); + m_state_bits_info.m_stencil_mode = StencilMode_e::TWO_SIDED; + } + else + { + assert(stateBits.loadBits[1] & GFXS1_STENCIL_FRONT_ENABLE); + m_state_bits_info.m_stencil_mode = StencilMode_e::ONE_SIDED; + } + } + 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); @@ -1248,6 +1277,7 @@ namespace IW4 SetValue("materialType", GdtMaterialTypeNames[static_cast(m_techset_info.m_gdt_material_type)]); SetValue("customTemplate", GdtCustomMaterialTypeNames[static_cast(m_techset_info.m_gdt_custom_material_type)]); SetValue("customString", m_techset_info.m_gdt_custom_string); + SetValue("sortKey", m_techset_info.m_sort_key_name); 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); @@ -1284,6 +1314,7 @@ namespace IW4 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("stencil", GdtStencilModeNames[static_cast(m_state_bits_info.m_stencil_mode)]); 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)]); @@ -1403,11 +1434,9 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfoWriteEntry(dumper.CreateGdtEntry()); } -#endif }