From 233d13ceb9dd340e015cb80dc8efcaf863859a56 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 7 May 2019 17:50:21 -1000 Subject: [PATCH] Refactor for blender 2.8 and new shader model --- CMakeLists.txt | 25 +- DataSpec/Blender/RetroMasterShader.py | 789 ++++++++++++- DataSpec/DNACommon/ANCS.cpp | 15 +- DataSpec/DNACommon/BabeDead.cpp | 20 +- DataSpec/DNACommon/CMDL.cpp | 172 +-- DataSpec/DNACommon/CMDL.hpp | 5 +- DataSpec/DNACommon/CMakeLists.txt | 2 +- DataSpec/DNACommon/DeafBabe.cpp | 18 +- DataSpec/DNACommon/GX.cpp | 18 + DataSpec/DNACommon/GX.hpp | 296 ++++- DataSpec/DNACommon/MAPA.cpp | 18 +- DataSpec/DNACommon/MAPU.cpp | 11 +- DataSpec/DNACommon/MLVL.cpp | 25 +- DataSpec/DNACommon/PAK.cpp | 2 +- DataSpec/DNAMP1/CINF.cpp | 11 +- DataSpec/DNAMP1/CMDL.cpp | 20 +- DataSpec/DNAMP1/CMDLMaterials.cpp | 1030 +++++++---------- DataSpec/DNAMP1/CMDLMaterials.hpp | 116 +- DataSpec/DNAMP1/DCLN.cpp | 33 +- DataSpec/DNAMP1/DCLN.hpp | 23 + DataSpec/DNAMP1/DeafBabe.cpp | 9 +- DataSpec/DNAMP1/FRME.cpp | 42 +- DataSpec/DNAMP1/MLVL.cpp | 10 +- DataSpec/DNAMP1/MLVL.hpp | 2 +- DataSpec/DNAMP1/MREA.cpp | 43 +- DataSpec/DNAMP1/PATH.cpp | 34 +- DataSpec/DNAMP2/CINF.cpp | 11 +- DataSpec/DNAMP2/DeafBabe.cpp | 2 - DataSpec/DNAMP2/MREA.cpp | 17 +- DataSpec/DNAMP3/CINF.cpp | 9 +- DataSpec/DNAMP3/CMDLMaterials.cpp | 16 +- DataSpec/DNAMP3/MREA.cpp | 21 +- DataSpec/SpecBase.cpp | 74 +- DataSpec/SpecBase.hpp | 9 +- DataSpec/SpecMP1.cpp | 20 +- DataSpec/SpecMP2.cpp | 7 +- DataSpec/SpecMP3.cpp | 7 +- Editor/ProjectManager.cpp | 4 +- Editor/ProjectResourceFactoryBase.cpp | 4 +- Editor/ProjectResourceFactoryBase.hpp | 10 +- Runtime/CMakeLists.txt | 8 +- Runtime/CPlayerState.cpp | 4 +- Runtime/CPlayerState.hpp | 2 +- Runtime/CStateManager.cpp | 2 +- Runtime/Graphics/CBooRenderer.cpp | 23 +- Runtime/Graphics/CBooRenderer.hpp | 9 +- Runtime/Graphics/CMakeLists.txt | 1 - Runtime/Graphics/CModel.hpp | 20 +- Runtime/Graphics/CModelBoo.cpp | 180 ++- Runtime/Graphics/Shaders/CModelShaders.cpp | 131 +-- Runtime/Graphics/Shaders/CModelShaders.hpp | 6 +- .../Graphics/Shaders/CModelShadersGLSL.cpp | 280 ----- .../Graphics/Shaders/CModelShadersHLSL.cpp | 271 ----- .../Graphics/Shaders/CModelShadersMetal.cpp | 276 ----- Runtime/World/CGameArea.cpp | 2 +- Runtime/World/CScriptPickup.cpp | 2 +- Runtime/World/CScriptPlayerStateChange.cpp | 2 +- Shaders/CMakeLists.txt | 6 +- Shaders/CModelShaders.common.glsl | 18 + Shaders/CModelShaders.frag.glsl | 348 ++++++ Shaders/CModelShaders.vert.glsl | 61 + Shaders/shader_CModelShaders.hpp | 59 + Shaders/shader_CModelShadersGLSL.cpp | 217 ++++ Shaders/shader_CModelShadersHLSL.cpp | 0 Shaders/shader_CModelShadersMetal.cpp | 0 hecl | 2 +- specter | 2 +- 67 files changed, 2827 insertions(+), 2105 deletions(-) create mode 100644 DataSpec/DNACommon/GX.cpp delete mode 100644 Runtime/Graphics/Shaders/CModelShadersGLSL.cpp delete mode 100644 Runtime/Graphics/Shaders/CModelShadersHLSL.cpp delete mode 100644 Runtime/Graphics/Shaders/CModelShadersMetal.cpp create mode 100644 Shaders/CModelShaders.common.glsl create mode 100644 Shaders/CModelShaders.frag.glsl create mode 100644 Shaders/CModelShaders.vert.glsl create mode 100644 Shaders/shader_CModelShaders.hpp create mode 100644 Shaders/shader_CModelShadersGLSL.cpp create mode 100644 Shaders/shader_CModelShadersHLSL.cpp create mode 100644 Shaders/shader_CModelShadersMetal.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 136c222bb..c205d0be0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,6 +130,13 @@ else() message(STATUS "Building with x87 Vector ISA") endif() + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-fno-plt HAS_NO_PLT) + if (HAS_NO_PLT) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-plt") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-plt") + endif() + if(URDE_MSAN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ -stdlib=libc++ -fsanitize=memory -fsanitize-memory-track-origins -fsanitize-recover=all") @@ -138,7 +145,7 @@ else() endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-multichar -Werror=implicit-fallthrough \ -Wno-unknown-warning-option -Wno-lto-type-mismatch -Wno-unused-variable -Wno-unused-private-field \ - -fno-exceptions -fno-rtti -Werror") + -Wno-unused-function -fno-exceptions -fno-rtti -Werror") if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations") @@ -194,6 +201,8 @@ set(HECL_DLPACKAGE ${URDE_DLPACKAGE}) set(BOO_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/hecl/extern/boo/include) set(HECL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/hecl/include ${CMAKE_CURRENT_SOURCE_DIR}/hecl/blender) +set(SPECTER_INCLUDE_DIR specter/include specter/freetype2/include) +set(ZEUS_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/specter/zeus/include) set(DATA_SPEC_LIBS RetroDataSpec amuse) set(HECL_DATASPEC_DECLS @@ -222,6 +231,9 @@ set(HECL_DATASPEC_PUSHES hecl::Database::DATA_SPEC_REGISTRY.push_back(&DataSpec::SpecEntMP3); hecl::Database::DATA_SPEC_REGISTRY.push_back(&DataSpec::SpecEntMP3PC); hecl::Database::DATA_SPEC_REGISTRY.push_back(&DataSpec::SpecEntMP3ORIG);") +add_definitions(-DZE_ATHENA_TYPES=1) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${SPECTER_INCLUDE_DIR} ${NOD_INCLUDE_DIR} + ${ZEUS_INCLUDE_DIR}) add_subdirectory(hecl/shaderc) include(hecl/ApplicationTools.cmake) add_subdirectory(specter/shaders) @@ -233,6 +245,11 @@ if(NOT TARGET bintoc) find_package(hecl-bintoc REQUIRED) endif() +bintoc(CModelShaders.common.glsl.cpp Shaders/CModelShaders.common.glsl CMODELSHADERS_COMMON_GLSL) +bintoc(CModelShaders.vert.glsl.cpp Shaders/CModelShaders.vert.glsl CMODELSHADERS_VERT_GLSL) +bintoc(CModelShaders.frag.glsl.cpp Shaders/CModelShaders.frag.glsl CMODELSHADERS_FRAG_GLSL) +add_library(CModelShaders CModelShaders.common.glsl.cpp CModelShaders.vert.glsl.cpp CModelShaders.frag.glsl.cpp) + if(NOT TARGET atdna) # Import native atdna if cross-compiling find_package(atdna REQUIRED) @@ -245,13 +262,9 @@ add_definitions(${BOO_SYS_DEFINES}) include_directories(${BOO_SYS_INCLUDES}) add_subdirectory(amuse) add_subdirectory(specter) -set(SPECTER_INCLUDE_DIR specter/include specter/freetype2/include) add_subdirectory(assetnameparser) -add_definitions(-DZE_ATHENA_TYPES=1) -set(ZEUS_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/specter/zeus/include) include_directories(${ATHENA_INCLUDE_DIR} ${LOGVISOR_INCLUDE_DIR} ${HECL_INCLUDE_DIR} - ${NOD_INCLUDE_DIR} ${ZEUS_INCLUDE_DIR} ${BOO_INCLUDE_DIR} ${AMUSE_INCLUDE_DIR} - ${SPECTER_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${BOO_INCLUDE_DIR} ${AMUSE_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/NESEmulator) add_subdirectory(NESEmulator) add_subdirectory(DataSpec) diff --git a/DataSpec/Blender/RetroMasterShader.py b/DataSpec/Blender/RetroMasterShader.py index e73c68071..53fc5f95e 100644 --- a/DataSpec/Blender/RetroMasterShader.py +++ b/DataSpec/Blender/RetroMasterShader.py @@ -2,6 +2,661 @@ import bpy +# Root Eevee Nodes + +#0 - RetroShader +def make_retro_shader(): + new_grp = bpy.data.node_groups.new('RetroShader', 'ShaderNodeTree') + lightmap_input = new_grp.inputs.new('NodeSocketColor', 'Lightmap') + lightmap_input.default_value = (0.0, 0.0, 0.0, 0.0) + diffuse_input = new_grp.inputs.new('NodeSocketColor', 'Diffuse') + diffuse_input.default_value = (0.0, 0.0, 0.0, 0.0) + emissive_input = new_grp.inputs.new('NodeSocketColor', 'Emissive') + emissive_input.default_value = (0.0, 0.0, 0.0, 0.0) + specular_input = new_grp.inputs.new('NodeSocketColor', 'Specular') + specular_input.default_value = (0.0, 0.0, 0.0, 0.0) + ext_spec_input = new_grp.inputs.new('NodeSocketColor', 'ExtendedSpecular') + ext_spec_input.default_value = (0.0, 0.0, 0.0, 0.0) + reflection_input = new_grp.inputs.new('NodeSocketColor', 'Reflection') + reflection_input.default_value = (0.0, 0.0, 0.0, 0.0) + indirect_tex = new_grp.inputs.new('NodeSocketColor', 'IndirectTex') + indirect_tex.default_value = (0.0, 0.0, 0.0, 0.0) + alpha_input = new_grp.inputs.new('NodeSocketFloatFactor', 'Alpha') + alpha_input.default_value = 1.0 + alpha_input.min_value = 0.0 + alpha_input.max_value = 1.0 + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-1280, 27) + + # New shader model + new_shader_model = new_grp.nodes.new('ShaderNodeValue') + new_shader_model.name = 'NewShaderModel' + new_shader_model.label = 'NewShaderModel' + new_shader_model.location = (-1280, 118) + new_shader_model.outputs[0].default_value = 0.0 + + # Principled BSDF (For new shader model) + principled_bsdf = new_grp.nodes.new('ShaderNodeBsdfPrincipled') + principled_bsdf.location = (-1038, 874) + principled_bsdf.inputs['Metallic'].default_value = 0.5 + + # Invert (for roughness) + invert = new_grp.nodes.new('ShaderNodeInvert') + invert.location = (-1256, 492) + invert.inputs[0].default_value = 1.0 + + # Gamma (for roughness) + gamma = new_grp.nodes.new('ShaderNodeGamma') + gamma.location = (-1256, 640) + gamma.inputs[1].default_value = 10.0 + + # Diffuse BSDF (Multiplies dynamic lighting with diffuse) + diffuse_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + diffuse_bdsf.location = (-945, 293) + + # Mix shader (interpolates Principled and Diffuse BSDF) + new_shader_model_mix1 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix1.location = (-760, 340) + + # Multiply (Multiplies static lightmap with diffuse) + lightmap_mult = new_grp.nodes.new('ShaderNodeMixRGB') + lightmap_mult.location = (-944, 122) + lightmap_mult.blend_type = 'MULTIPLY' + lightmap_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies specular with reflection) + specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + specular_mult.location = (-940, -105) + specular_mult.blend_type = 'MULTIPLY' + specular_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies extended specular with reflection) + extended_specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + extended_specular_mult.location = (-941, -304) + extended_specular_mult.blend_type = 'MULTIPLY' + extended_specular_mult.inputs['Fac'].default_value = 1.0 + + # Add Shader (Adds dynamic diffuse with static diffuse) + diffuse_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + diffuse_add_shader.location = (-587, 209) + + # Mix shader (interpolates resolved reflection with nothing) + new_shader_model_mix2 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix2.location = (-512, -38) + + # Add Shader (Adds emissive with resolved reflection) + emissive_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + emissive_add_shader.location = (-320, 8) + + # Add Shader (Adds specular and extended specular reflections) + specular_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + specular_add_shader.location = (-734, -81) + + # Diffuse BDSF (Multiplies extended specular with dynamic lighting) + extended_specular_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + extended_specular_bdsf.location = (-738, -280) + + # Add shader (Adds diffuse with all emissive sources) + final_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + final_add_shader.location = (-184, 234) + + # Transparent BDSF (Provides alpha) + transparent_bdsf = new_grp.nodes.new('ShaderNodeBsdfTransparent') + transparent_bdsf.location = (-224, -160) + transparent_bdsf.inputs['Color'].default_value = (1.0, 1.0, 1.0, 1.0) + + # Mix Shader (Applies alpha proportion) + alpha_mix = new_grp.nodes.new('ShaderNodeMixShader') + alpha_mix.location = (-40, -112) + + # Material Output (Final output) + mat_out = new_grp.nodes.new('ShaderNodeOutputMaterial') + mat_out.location = (150, -88) + + # Links + new_grp.links.new(grp_in.outputs['Lightmap'], lightmap_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Diffuse'], lightmap_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_bdsf.inputs['Color']) + new_grp.links.new(grp_in.outputs['Diffuse'], principled_bsdf.inputs['Base Color']) + new_grp.links.new(grp_in.outputs['Emissive'], emissive_add_shader.inputs[0]) + new_grp.links.new(grp_in.outputs['Specular'], specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Specular'], principled_bsdf.inputs['Specular']) + new_grp.links.new(grp_in.outputs['ExtendedSpecular'], extended_specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Reflection'], specular_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Reflection'], extended_specular_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Alpha'], alpha_mix.inputs['Fac']) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix1.inputs[0]) + new_grp.links.new(diffuse_bdsf.outputs['BSDF'], new_shader_model_mix1.inputs[1]) + new_grp.links.new(grp_in.outputs['Specular'], invert.inputs['Color']) + new_grp.links.new(invert.outputs['Color'], gamma.inputs['Color']) + new_grp.links.new(gamma.outputs['Color'], principled_bsdf.inputs['Roughness']) + new_grp.links.new(principled_bsdf.outputs['BSDF'], new_shader_model_mix1.inputs[2]) + new_grp.links.new(new_shader_model_mix1.outputs['Shader'], diffuse_add_shader.inputs[0]) + new_grp.links.new(lightmap_mult.outputs['Color'], diffuse_add_shader.inputs[1]) + new_grp.links.new(specular_mult.outputs['Color'], specular_add_shader.inputs[0]) + new_grp.links.new(extended_specular_mult.outputs['Color'], extended_specular_bdsf.inputs['Color']) + new_grp.links.new(extended_specular_bdsf.outputs['BSDF'], specular_add_shader.inputs[1]) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix2.inputs[0]) + new_grp.links.new(specular_add_shader.outputs['Shader'], new_shader_model_mix2.inputs[1]) + new_grp.links.new(new_shader_model_mix2.outputs['Shader'], emissive_add_shader.inputs[1]) + new_grp.links.new(diffuse_add_shader.outputs['Shader'], final_add_shader.inputs[0]) + new_grp.links.new(emissive_add_shader.outputs['Shader'], final_add_shader.inputs[1]) + new_grp.links.new(transparent_bdsf.outputs['BSDF'], alpha_mix.inputs[1]) + new_grp.links.new(final_add_shader.outputs['Shader'], alpha_mix.inputs[2]) + new_grp.links.new(alpha_mix.outputs['Shader'], mat_out.inputs['Surface']) + +def make_retro_dynamic_shader(): + new_grp = bpy.data.node_groups.new('RetroDynamicShader', 'ShaderNodeTree') + lightmap_input = new_grp.inputs.new('NodeSocketColor', 'Lightmap') + lightmap_input.default_value = (0.0, 0.0, 0.0, 0.0) + diffuse_input = new_grp.inputs.new('NodeSocketColor', 'Diffuse') + diffuse_input.default_value = (0.0, 0.0, 0.0, 0.0) + emissive_input = new_grp.inputs.new('NodeSocketColor', 'Emissive') + emissive_input.default_value = (0.0, 0.0, 0.0, 0.0) + specular_input = new_grp.inputs.new('NodeSocketColor', 'Specular') + specular_input.default_value = (0.0, 0.0, 0.0, 0.0) + ext_spec_input = new_grp.inputs.new('NodeSocketColor', 'ExtendedSpecular') + ext_spec_input.default_value = (0.0, 0.0, 0.0, 0.0) + reflection_input = new_grp.inputs.new('NodeSocketColor', 'Reflection') + reflection_input.default_value = (0.0, 0.0, 0.0, 0.0) + indirect_tex = new_grp.inputs.new('NodeSocketColor', 'IndirectTex') + indirect_tex.default_value = (0.0, 0.0, 0.0, 0.0) + alpha_input = new_grp.inputs.new('NodeSocketFloatFactor', 'Alpha') + alpha_input.default_value = 1.0 + alpha_input.min_value = 0.0 + alpha_input.max_value = 1.0 + dynamic_input = new_grp.inputs.new('NodeSocketColor', 'DynamicTest') + dynamic_input.default_value = (1.0, 1.0, 1.0, 1.0) + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-1460, 27) + + # Multiply (Lightmap dynamic) + lightmap_dynamic = new_grp.nodes.new('ShaderNodeMixRGB') + lightmap_dynamic.location = (-1174, 158) + lightmap_dynamic.blend_type = 'MULTIPLY' + lightmap_dynamic.inputs['Fac'].default_value = 1.0 + + # Multiply (Diffuse dynamic) + diffuse_dynamic = new_grp.nodes.new('ShaderNodeMixRGB') + diffuse_dynamic.location = (-1174, -32) + diffuse_dynamic.blend_type = 'MULTIPLY' + diffuse_dynamic.inputs['Fac'].default_value = 1.0 + + # Multiply (Emissive dynamic) + emissive_dynamic = new_grp.nodes.new('ShaderNodeMixRGB') + emissive_dynamic.location = (-1174, -222) + emissive_dynamic.blend_type = 'MULTIPLY' + emissive_dynamic.inputs['Fac'].default_value = 1.0 + + # New shader model + new_shader_model = new_grp.nodes.new('ShaderNodeValue') + new_shader_model.name = 'NewShaderModel' + new_shader_model.label = 'NewShaderModel' + new_shader_model.location = (-1460, 118) + new_shader_model.outputs[0].default_value = 0.0 + + # Principled BSDF (For new shader model) + principled_bsdf = new_grp.nodes.new('ShaderNodeBsdfPrincipled') + principled_bsdf.location = (-1038, 874) + principled_bsdf.inputs['Metallic'].default_value = 0.5 + + # Invert (for roughness) + invert = new_grp.nodes.new('ShaderNodeInvert') + invert.location = (-1256, 492) + invert.inputs[0].default_value = 1.0 + + # Gamma (for roughness) + gamma = new_grp.nodes.new('ShaderNodeGamma') + gamma.location = (-1256, 640) + gamma.inputs[1].default_value = 10.0 + + # Diffuse BSDF (Multiplies dynamic lighting with diffuse) + diffuse_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + diffuse_bdsf.location = (-945, 293) + + # Mix shader (interpolates Principled and Diffuse BSDF) + new_shader_model_mix1 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix1.location = (-760, 340) + + # Multiply (Multiplies static lightmap with diffuse) + lightmap_mult = new_grp.nodes.new('ShaderNodeMixRGB') + lightmap_mult.location = (-944, 122) + lightmap_mult.blend_type = 'MULTIPLY' + lightmap_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies specular with reflection) + specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + specular_mult.location = (-940, -105) + specular_mult.blend_type = 'MULTIPLY' + specular_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies extended specular with reflection) + extended_specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + extended_specular_mult.location = (-941, -304) + extended_specular_mult.blend_type = 'MULTIPLY' + extended_specular_mult.inputs['Fac'].default_value = 1.0 + + # Add Shader (Adds dynamic diffuse with static diffuse) + diffuse_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + diffuse_add_shader.location = (-587, 209) + + # Mix shader (interpolates resolved reflection with nothing) + new_shader_model_mix2 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix2.location = (-512, -38) + + # Add Shader (Adds emissive with resolved reflection) + emissive_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + emissive_add_shader.location = (-320, 8) + + # Add Shader (Adds specular and extended specular reflections) + specular_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + specular_add_shader.location = (-734, -81) + + # Diffuse BDSF (Multiplies extended specular with dynamic lighting) + extended_specular_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + extended_specular_bdsf.location = (-738, -280) + + # Add shader (Adds diffuse with all emissive sources) + final_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + final_add_shader.location = (-184, 234) + + # Transparent BDSF (Provides alpha) + transparent_bdsf = new_grp.nodes.new('ShaderNodeBsdfTransparent') + transparent_bdsf.location = (-224, -160) + transparent_bdsf.inputs['Color'].default_value = (1.0, 1.0, 1.0, 1.0) + + # Mix Shader (Applies alpha proportion) + alpha_mix = new_grp.nodes.new('ShaderNodeMixShader') + alpha_mix.location = (-40, -112) + + # Material Output (Final output) + mat_out = new_grp.nodes.new('ShaderNodeOutputMaterial') + mat_out.location = (150, -88) + + # Links + new_grp.links.new(grp_in.outputs['Lightmap'], lightmap_dynamic.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DynamicTest'], lightmap_dynamic.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_dynamic.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DynamicTest'], diffuse_dynamic.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Emissive'], emissive_dynamic.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DynamicTest'], emissive_dynamic.inputs['Color2']) + new_grp.links.new(lightmap_dynamic.outputs['Color'], lightmap_mult.inputs['Color1']) + new_grp.links.new(diffuse_dynamic.outputs['Color'], lightmap_mult.inputs['Color2']) + new_grp.links.new(diffuse_dynamic.outputs['Color'], diffuse_bdsf.inputs['Color']) + new_grp.links.new(diffuse_dynamic.outputs['Color'], principled_bsdf.inputs['Base Color']) + new_grp.links.new(emissive_dynamic.outputs['Color'], emissive_add_shader.inputs[0]) + new_grp.links.new(grp_in.outputs['Specular'], specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Specular'], principled_bsdf.inputs['Specular']) + new_grp.links.new(grp_in.outputs['ExtendedSpecular'], extended_specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Reflection'], specular_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Reflection'], extended_specular_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Alpha'], alpha_mix.inputs['Fac']) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix1.inputs[0]) + new_grp.links.new(diffuse_bdsf.outputs['BSDF'], new_shader_model_mix1.inputs[1]) + new_grp.links.new(grp_in.outputs['Specular'], invert.inputs['Color']) + new_grp.links.new(invert.outputs['Color'], gamma.inputs['Color']) + new_grp.links.new(gamma.outputs['Color'], principled_bsdf.inputs['Roughness']) + new_grp.links.new(principled_bsdf.outputs['BSDF'], new_shader_model_mix1.inputs[2]) + new_grp.links.new(new_shader_model_mix1.outputs['Shader'], diffuse_add_shader.inputs[0]) + new_grp.links.new(lightmap_mult.outputs['Color'], diffuse_add_shader.inputs[1]) + new_grp.links.new(specular_mult.outputs['Color'], specular_add_shader.inputs[0]) + new_grp.links.new(extended_specular_mult.outputs['Color'], extended_specular_bdsf.inputs['Color']) + new_grp.links.new(extended_specular_bdsf.outputs['BSDF'], specular_add_shader.inputs[1]) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix2.inputs[0]) + new_grp.links.new(specular_add_shader.outputs['Shader'], new_shader_model_mix2.inputs[1]) + new_grp.links.new(new_shader_model_mix2.outputs['Shader'], emissive_add_shader.inputs[1]) + new_grp.links.new(diffuse_add_shader.outputs['Shader'], final_add_shader.inputs[0]) + new_grp.links.new(emissive_add_shader.outputs['Shader'], final_add_shader.inputs[1]) + new_grp.links.new(transparent_bdsf.outputs['BSDF'], alpha_mix.inputs[1]) + new_grp.links.new(final_add_shader.outputs['Shader'], alpha_mix.inputs[2]) + new_grp.links.new(alpha_mix.outputs['Shader'], mat_out.inputs['Surface']) + +def make_retro_dynamic_alpha_shader(): + new_grp = bpy.data.node_groups.new('RetroDynamicAlphaShader', 'ShaderNodeTree') + lightmap_input = new_grp.inputs.new('NodeSocketColor', 'Lightmap') + lightmap_input.default_value = (0.0, 0.0, 0.0, 0.0) + diffuse_input = new_grp.inputs.new('NodeSocketColor', 'Diffuse') + diffuse_input.default_value = (0.0, 0.0, 0.0, 0.0) + emissive_input = new_grp.inputs.new('NodeSocketColor', 'Emissive') + emissive_input.default_value = (0.0, 0.0, 0.0, 0.0) + specular_input = new_grp.inputs.new('NodeSocketColor', 'Specular') + specular_input.default_value = (0.0, 0.0, 0.0, 0.0) + ext_spec_input = new_grp.inputs.new('NodeSocketColor', 'ExtendedSpecular') + ext_spec_input.default_value = (0.0, 0.0, 0.0, 0.0) + reflection_input = new_grp.inputs.new('NodeSocketColor', 'Reflection') + reflection_input.default_value = (0.0, 0.0, 0.0, 0.0) + indirect_tex = new_grp.inputs.new('NodeSocketColor', 'IndirectTex') + indirect_tex.default_value = (0.0, 0.0, 0.0, 0.0) + alpha_input = new_grp.inputs.new('NodeSocketFloatFactor', 'Alpha') + alpha_input.default_value = 1.0 + alpha_input.min_value = 0.0 + alpha_input.max_value = 1.0 + dynamic_input = new_grp.inputs.new('NodeSocketColor', 'DynamicTest') + dynamic_input.default_value = (1.0, 1.0, 1.0, 1.0) + dynamic_alpha_input = new_grp.inputs.new('NodeSocketFloatFactor', 'DynamicAlphaTest') + dynamic_alpha_input.default_value = 1.0 + dynamic_alpha_input.min_value = 0.0 + dynamic_alpha_input.max_value = 1.0 + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-1460, 27) + + # Multiply (Lightmap dynamic) + lightmap_dynamic = new_grp.nodes.new('ShaderNodeMixRGB') + lightmap_dynamic.location = (-1174, 158) + lightmap_dynamic.blend_type = 'MULTIPLY' + lightmap_dynamic.inputs['Fac'].default_value = 1.0 + + # Multiply (Diffuse dynamic) + diffuse_dynamic = new_grp.nodes.new('ShaderNodeMixRGB') + diffuse_dynamic.location = (-1174, -32) + diffuse_dynamic.blend_type = 'MULTIPLY' + diffuse_dynamic.inputs['Fac'].default_value = 1.0 + + # Multiply (Emissive dynamic) + emissive_dynamic = new_grp.nodes.new('ShaderNodeMixRGB') + emissive_dynamic.location = (-1174, -222) + emissive_dynamic.blend_type = 'MULTIPLY' + emissive_dynamic.inputs['Fac'].default_value = 1.0 + + # Multiply (Alpha dynamic) + alpha_dynamic = new_grp.nodes.new('ShaderNodeMath') + alpha_dynamic.location = (-1174, -410) + alpha_dynamic.operation = 'MULTIPLY' + + # New shader model + new_shader_model = new_grp.nodes.new('ShaderNodeValue') + new_shader_model.name = 'NewShaderModel' + new_shader_model.label = 'NewShaderModel' + new_shader_model.location = (-1460, 118) + new_shader_model.outputs[0].default_value = 0.0 + + # Principled BSDF (For new shader model) + principled_bsdf = new_grp.nodes.new('ShaderNodeBsdfPrincipled') + principled_bsdf.location = (-1038, 874) + principled_bsdf.inputs['Metallic'].default_value = 0.5 + + # Invert (for roughness) + invert = new_grp.nodes.new('ShaderNodeInvert') + invert.location = (-1256, 492) + invert.inputs[0].default_value = 1.0 + + # Gamma (for roughness) + gamma = new_grp.nodes.new('ShaderNodeGamma') + gamma.location = (-1256, 640) + gamma.inputs[1].default_value = 10.0 + + # Diffuse BSDF (Multiplies dynamic lighting with diffuse) + diffuse_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + diffuse_bdsf.location = (-945, 293) + + # Mix shader (interpolates Principled and Diffuse BSDF) + new_shader_model_mix1 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix1.location = (-760, 340) + + # Multiply (Multiplies static lightmap with diffuse) + lightmap_mult = new_grp.nodes.new('ShaderNodeMixRGB') + lightmap_mult.location = (-944, 122) + lightmap_mult.blend_type = 'MULTIPLY' + lightmap_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies specular with reflection) + specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + specular_mult.location = (-940, -105) + specular_mult.blend_type = 'MULTIPLY' + specular_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies extended specular with reflection) + extended_specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + extended_specular_mult.location = (-941, -304) + extended_specular_mult.blend_type = 'MULTIPLY' + extended_specular_mult.inputs['Fac'].default_value = 1.0 + + # Add Shader (Adds dynamic diffuse with static diffuse) + diffuse_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + diffuse_add_shader.location = (-587, 209) + + # Mix shader (interpolates resolved reflection with nothing) + new_shader_model_mix2 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix2.location = (-512, -38) + + # Add Shader (Adds emissive with resolved reflection) + emissive_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + emissive_add_shader.location = (-320, 8) + + # Add Shader (Adds specular and extended specular reflections) + specular_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + specular_add_shader.location = (-734, -81) + + # Diffuse BDSF (Multiplies extended specular with dynamic lighting) + extended_specular_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + extended_specular_bdsf.location = (-738, -280) + + # Add shader (Adds diffuse with all emissive sources) + final_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + final_add_shader.location = (-184, 234) + + # Transparent BDSF (Provides alpha) + transparent_bdsf = new_grp.nodes.new('ShaderNodeBsdfTransparent') + transparent_bdsf.location = (-224, -160) + transparent_bdsf.inputs['Color'].default_value = (1.0, 1.0, 1.0, 1.0) + + # Mix Shader (Applies alpha proportion) + alpha_mix = new_grp.nodes.new('ShaderNodeMixShader') + alpha_mix.location = (-40, -112) + + # Material Output (Final output) + mat_out = new_grp.nodes.new('ShaderNodeOutputMaterial') + mat_out.location = (150, -88) + + # Links + new_grp.links.new(grp_in.outputs['Lightmap'], lightmap_dynamic.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DynamicTest'], lightmap_dynamic.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_dynamic.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DynamicTest'], diffuse_dynamic.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Emissive'], emissive_dynamic.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DynamicTest'], emissive_dynamic.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Alpha'], alpha_dynamic.inputs[0]) + new_grp.links.new(grp_in.outputs['DynamicAlphaTest'], alpha_dynamic.inputs[1]) + new_grp.links.new(lightmap_dynamic.outputs['Color'], lightmap_mult.inputs['Color1']) + new_grp.links.new(diffuse_dynamic.outputs['Color'], lightmap_mult.inputs['Color2']) + new_grp.links.new(diffuse_dynamic.outputs['Color'], diffuse_bdsf.inputs['Color']) + new_grp.links.new(diffuse_dynamic.outputs['Color'], principled_bsdf.inputs['Base Color']) + new_grp.links.new(emissive_dynamic.outputs['Color'], emissive_add_shader.inputs[0]) + new_grp.links.new(grp_in.outputs['Specular'], specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Specular'], principled_bsdf.inputs['Specular']) + new_grp.links.new(grp_in.outputs['ExtendedSpecular'], extended_specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Reflection'], specular_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Reflection'], extended_specular_mult.inputs['Color2']) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix1.inputs[0]) + new_grp.links.new(diffuse_bdsf.outputs['BSDF'], new_shader_model_mix1.inputs[1]) + new_grp.links.new(grp_in.outputs['Specular'], invert.inputs['Color']) + new_grp.links.new(invert.outputs['Color'], gamma.inputs['Color']) + new_grp.links.new(gamma.outputs['Color'], principled_bsdf.inputs['Roughness']) + new_grp.links.new(principled_bsdf.outputs['BSDF'], new_shader_model_mix1.inputs[2]) + new_grp.links.new(new_shader_model_mix1.outputs['Shader'], diffuse_add_shader.inputs[0]) + new_grp.links.new(alpha_dynamic.outputs['Value'], alpha_mix.inputs['Fac']) + new_grp.links.new(lightmap_mult.outputs['Color'], diffuse_add_shader.inputs[1]) + new_grp.links.new(specular_mult.outputs['Color'], specular_add_shader.inputs[0]) + new_grp.links.new(extended_specular_mult.outputs['Color'], extended_specular_bdsf.inputs['Color']) + new_grp.links.new(extended_specular_bdsf.outputs['BSDF'], specular_add_shader.inputs[1]) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix2.inputs[0]) + new_grp.links.new(specular_add_shader.outputs['Shader'], new_shader_model_mix2.inputs[1]) + new_grp.links.new(new_shader_model_mix2.outputs['Shader'], emissive_add_shader.inputs[1]) + new_grp.links.new(diffuse_add_shader.outputs['Shader'], final_add_shader.inputs[0]) + new_grp.links.new(emissive_add_shader.outputs['Shader'], final_add_shader.inputs[1]) + new_grp.links.new(transparent_bdsf.outputs['BSDF'], alpha_mix.inputs[1]) + new_grp.links.new(final_add_shader.outputs['Shader'], alpha_mix.inputs[2]) + new_grp.links.new(alpha_mix.outputs['Shader'], mat_out.inputs['Surface']) + +def make_retro_dynamic_character_shader(): + new_grp = bpy.data.node_groups.new('RetroDynamicCharacterShader', 'ShaderNodeTree') + lightmap_input = new_grp.inputs.new('NodeSocketColor', 'Lightmap') + lightmap_input.default_value = (0.0, 0.0, 0.0, 0.0) + diffuse_input = new_grp.inputs.new('NodeSocketColor', 'Diffuse') + diffuse_input.default_value = (0.0, 0.0, 0.0, 0.0) + emissive_input = new_grp.inputs.new('NodeSocketColor', 'Emissive') + emissive_input.default_value = (0.0, 0.0, 0.0, 0.0) + specular_input = new_grp.inputs.new('NodeSocketColor', 'Specular') + specular_input.default_value = (0.0, 0.0, 0.0, 0.0) + ext_spec_input = new_grp.inputs.new('NodeSocketColor', 'ExtendedSpecular') + ext_spec_input.default_value = (0.0, 0.0, 0.0, 0.0) + reflection_input = new_grp.inputs.new('NodeSocketColor', 'Reflection') + reflection_input.default_value = (0.0, 0.0, 0.0, 0.0) + indirect_tex = new_grp.inputs.new('NodeSocketColor', 'IndirectTex') + indirect_tex.default_value = (0.0, 0.0, 0.0, 0.0) + alpha_input = new_grp.inputs.new('NodeSocketFloatFactor', 'Alpha') + alpha_input.default_value = 1.0 + alpha_input.min_value = 0.0 + alpha_input.max_value = 1.0 + dynamic_input = new_grp.inputs.new('NodeSocketColor', 'DynamicTest') + dynamic_input.default_value = (1.0, 1.0, 1.0, 1.0) + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-1460, 27) + + # Multiply (Emissive dynamic) + emissive_dynamic = new_grp.nodes.new('ShaderNodeMixRGB') + emissive_dynamic.location = (-1174, -32) + emissive_dynamic.blend_type = 'MULTIPLY' + emissive_dynamic.inputs['Fac'].default_value = 1.0 + + # New shader model + new_shader_model = new_grp.nodes.new('ShaderNodeValue') + new_shader_model.name = 'NewShaderModel' + new_shader_model.label = 'NewShaderModel' + new_shader_model.location = (-1460, 118) + new_shader_model.outputs[0].default_value = 0.0 + + # Principled BSDF (For new shader model) + principled_bsdf = new_grp.nodes.new('ShaderNodeBsdfPrincipled') + principled_bsdf.location = (-1038, 874) + principled_bsdf.inputs['Metallic'].default_value = 0.5 + + # Invert (for roughness) + invert = new_grp.nodes.new('ShaderNodeInvert') + invert.location = (-1256, 492) + invert.inputs[0].default_value = 1.0 + + # Gamma (for roughness) + gamma = new_grp.nodes.new('ShaderNodeGamma') + gamma.location = (-1256, 640) + gamma.inputs[1].default_value = 10.0 + + # Diffuse BSDF (Multiplies dynamic lighting with diffuse) + diffuse_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + diffuse_bdsf.location = (-945, 293) + + # Mix shader (interpolates Principled and Diffuse BSDF) + new_shader_model_mix1 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix1.location = (-760, 340) + + # Multiply (Multiplies static lightmap with diffuse) + lightmap_mult = new_grp.nodes.new('ShaderNodeMixRGB') + lightmap_mult.location = (-944, 122) + lightmap_mult.blend_type = 'MULTIPLY' + lightmap_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies specular with reflection) + specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + specular_mult.location = (-940, -105) + specular_mult.blend_type = 'MULTIPLY' + specular_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiplies extended specular with reflection) + extended_specular_mult = new_grp.nodes.new('ShaderNodeMixRGB') + extended_specular_mult.location = (-941, -304) + extended_specular_mult.blend_type = 'MULTIPLY' + extended_specular_mult.inputs['Fac'].default_value = 1.0 + + # Add Shader (Adds dynamic diffuse with static diffuse) + diffuse_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + diffuse_add_shader.location = (-587, 209) + + # Mix shader (interpolates resolved reflection with nothing) + new_shader_model_mix2 = new_grp.nodes.new('ShaderNodeMixShader') + new_shader_model_mix2.location = (-512, -38) + + # Add Shader (Adds emissive with resolved reflection) + emissive_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + emissive_add_shader.location = (-320, 8) + + # Add Shader (Adds specular and extended specular reflections) + specular_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + specular_add_shader.location = (-734, -81) + + # Diffuse BDSF (Multiplies extended specular with dynamic lighting) + extended_specular_bdsf = new_grp.nodes.new('ShaderNodeBsdfDiffuse') + extended_specular_bdsf.location = (-738, -280) + + # Add shader (Adds diffuse with all emissive sources) + final_add_shader = new_grp.nodes.new('ShaderNodeAddShader') + final_add_shader.location = (-184, 234) + + # Transparent BDSF (Provides alpha) + transparent_bdsf = new_grp.nodes.new('ShaderNodeBsdfTransparent') + transparent_bdsf.location = (-224, -160) + transparent_bdsf.inputs['Color'].default_value = (1.0, 1.0, 1.0, 1.0) + + # Mix Shader (Applies alpha proportion) + alpha_mix = new_grp.nodes.new('ShaderNodeMixShader') + alpha_mix.location = (-40, -112) + + # Material Output (Final output) + mat_out = new_grp.nodes.new('ShaderNodeOutputMaterial') + mat_out.location = (150, -88) + + # Links + new_grp.links.new(grp_in.outputs['Emissive'], emissive_dynamic.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DynamicTest'], emissive_dynamic.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Lightmap'], lightmap_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Diffuse'], lightmap_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_bdsf.inputs['Color']) + new_grp.links.new(grp_in.outputs['Diffuse'], principled_bsdf.inputs['Base Color']) + new_grp.links.new(emissive_dynamic.outputs['Color'], emissive_add_shader.inputs[0]) + new_grp.links.new(grp_in.outputs['Specular'], specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Specular'], principled_bsdf.inputs['Specular']) + new_grp.links.new(grp_in.outputs['ExtendedSpecular'], extended_specular_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['Reflection'], specular_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Reflection'], extended_specular_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Alpha'], alpha_mix.inputs['Fac']) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix1.inputs[0]) + new_grp.links.new(diffuse_bdsf.outputs['BSDF'], new_shader_model_mix1.inputs[1]) + new_grp.links.new(grp_in.outputs['Specular'], invert.inputs['Color']) + new_grp.links.new(invert.outputs['Color'], gamma.inputs['Color']) + new_grp.links.new(gamma.outputs['Color'], principled_bsdf.inputs['Roughness']) + new_grp.links.new(principled_bsdf.outputs['BSDF'], new_shader_model_mix1.inputs[2]) + new_grp.links.new(new_shader_model_mix1.outputs['Shader'], diffuse_add_shader.inputs[0]) + new_grp.links.new(lightmap_mult.outputs['Color'], diffuse_add_shader.inputs[1]) + new_grp.links.new(specular_mult.outputs['Color'], specular_add_shader.inputs[0]) + new_grp.links.new(extended_specular_mult.outputs['Color'], extended_specular_bdsf.inputs['Color']) + new_grp.links.new(extended_specular_bdsf.outputs['BSDF'], specular_add_shader.inputs[1]) + new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix2.inputs[0]) + new_grp.links.new(specular_add_shader.outputs['Shader'], new_shader_model_mix2.inputs[1]) + new_grp.links.new(new_shader_model_mix2.outputs['Shader'], emissive_add_shader.inputs[1]) + new_grp.links.new(diffuse_add_shader.outputs['Shader'], final_add_shader.inputs[0]) + new_grp.links.new(emissive_add_shader.outputs['Shader'], final_add_shader.inputs[1]) + new_grp.links.new(transparent_bdsf.outputs['BSDF'], alpha_mix.inputs[1]) + new_grp.links.new(final_add_shader.outputs['Shader'], alpha_mix.inputs[2]) + new_grp.links.new(alpha_mix.outputs['Shader'], mat_out.inputs['Surface']) + +ROOT_SHADER_GROUPS = ( + make_retro_shader, + make_retro_dynamic_shader, + make_retro_dynamic_alpha_shader, + make_retro_dynamic_character_shader +) + # UV animation nodes: # http://www.metroid2002.com/retromodding/wiki/Materials_(Metroid_Prime)#UV_Animations @@ -18,17 +673,28 @@ def make_uva0(): # Group outputs grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (500, 0) - - # UV vertical-flip (to match GameCube's UV-coordinate space) - v_flip = new_grp.nodes.new('ShaderNodeMapping') - v_flip.location = (100, 0) - v_flip.vector_type = 'TEXTURE' - v_flip.scale[1] = -1.0 + grp_out.location = (1000, 0) + + # Vector Transform to bring world space into camera space + vec_xf = new_grp.nodes.new('ShaderNodeVectorTransform') + vec_xf.location = (100, 0) + vec_xf.vector_type = 'NORMAL' + vec_xf.convert_from = 'WORLD' + vec_xf.convert_to = 'CAMERA' + + # UV scale (to match GameCube's UV-coordinate space) + uv_scale = new_grp.nodes.new('ShaderNodeMapping') + uv_scale.location = (400, -400) + uv_scale.vector_type = 'TEXTURE' + uv_scale.scale[0] = 2.0 + uv_scale.scale[1] = 2.0 + uv_scale.translation[0] = 1.0 + uv_scale.translation[1] = 1.0 # Links - new_grp.links.new(grp_in.outputs[0], v_flip.inputs[0]) - new_grp.links.new(v_flip.outputs[0], grp_out.inputs[0]) + new_grp.links.new(grp_in.outputs[0], vec_xf.inputs[0]) + new_grp.links.new(vec_xf.outputs[0], uv_scale.inputs[0]) + new_grp.links.new(uv_scale.outputs[0], grp_out.inputs[0]) # 1 - Modelview Inverse def make_uva1(): @@ -36,42 +702,17 @@ def make_uva1(): new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.outputs.new('NodeSocketVector', 'UV Out') new_grp.use_fake_user = True - + # Group inputs grp_in = new_grp.nodes.new('NodeGroupInput') grp_in.location = (-300, 0) - + # Group outputs grp_out = new_grp.nodes.new('NodeGroupOutput') grp_out.location = (500, 0) - # Geometry input - geom_in = new_grp.nodes.new('ShaderNodeGeometry') - geom_in.location = (-700, 0) - - # View flip - view_flip = new_grp.nodes.new('ShaderNodeMapping') - view_flip.location = (-500, -100) - view_flip.vector_type = 'TEXTURE' - view_flip.scale = (-1.0, -1.0, 1.0) - - # Normal/translation add - adder = new_grp.nodes.new('ShaderNodeVectorMath') - adder.location = (-100, 0) - adder.operation = 'ADD' - - # UV vertical-flip (to match GameCube's UV-coordinate space) - v_flip = new_grp.nodes.new('ShaderNodeMapping') - v_flip.location = (100, 0) - v_flip.vector_type = 'TEXTURE' - v_flip.scale[1] = -1.0 - # Links - new_grp.links.new(grp_in.outputs[0], adder.inputs[0]) - new_grp.links.new(geom_in.outputs['View'], view_flip.inputs[0]) - new_grp.links.new(view_flip.outputs[0], adder.inputs[1]) - new_grp.links.new(adder.outputs[0], v_flip.inputs[0]) - new_grp.links.new(v_flip.outputs[0], grp_out.inputs[0]) + new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) # 2 - UV Scroll def make_uva2(): @@ -84,11 +725,18 @@ def make_uva2(): # Group inputs grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-100, 0) + grp_in.location = (-457, 22) # Group outputs grp_out = new_grp.nodes.new('NodeGroupOutput') grp_out.location = (500, 0) + + # Mapping + mapping = new_grp.nodes.new('ShaderNodeMapping') + mapping.location = (-235, 125) + drvs = mapping.driver_add('scale') + for drv in drvs: + drv.driver.expression = 'frame/60' # Adder1 adder1 = new_grp.nodes.new('ShaderNodeVectorMath') @@ -103,7 +751,8 @@ def make_uva2(): # Links new_grp.links.new(grp_in.outputs[0], adder2.inputs[0]) new_grp.links.new(grp_in.outputs[1], adder1.inputs[0]) - new_grp.links.new(grp_in.outputs[2], adder1.inputs[1]) + new_grp.links.new(grp_in.outputs[2], mapping.inputs[0]) + new_grp.links.new(mapping.outputs[0], adder1.inputs[1]) new_grp.links.new(adder1.outputs[0], adder2.inputs[1]) new_grp.links.new(adder2.outputs[0], grp_out.inputs[0]) @@ -128,11 +777,19 @@ def make_uva3(): add1 = new_grp.nodes.new('ShaderNodeMath') add1.operation = 'ADD' add1.location = (500, 0) + + # Multiply + mult = new_grp.nodes.new('ShaderNodeMath') + mult.operation = 'MULTIPLY' + mult.location = (230, -112) + drv = mult.inputs[1].driver_add('default_value') + drv.driver.expression = 'frame/60' # Links new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) new_grp.links.new(grp_in.outputs[1], add1.inputs[0]) - new_grp.links.new(grp_in.outputs[2], add1.inputs[1]) + new_grp.links.new(grp_in.outputs[2], mult.inputs[0]) + new_grp.links.new(mult.outputs[0], add1.inputs[1]) # 4 - Horizontal Filmstrip Animation def make_uva4(): @@ -166,7 +823,7 @@ def make_uva4(): # Modulo mod1 = new_grp.nodes.new('ShaderNodeMath') mod1.operation = 'MODULO' - mod1.inputs[1].default_value = 900.0 + mod1.inputs[1].default_value = 1.0 mod1.location = (-400, 0) # Multiply3 @@ -188,6 +845,19 @@ def make_uva4(): add1 = new_grp.nodes.new('ShaderNodeVectorMath') add1.operation = 'ADD' add1.location = (600, 0) + + # Timing Add + time_add = new_grp.nodes.new('ShaderNodeMath') + time_add.operation = 'ADD' + time_add.location = (-802, -180) + drv = time_add.inputs[1].driver_add('default_value') + drv.driver.expression = 'frame/60' + + # Floor + floor = new_grp.nodes.new('ShaderNodeMath') + floor.operation = 'FLOOR' + floor.location = (-204, -180) + floor.inputs[1].default_value = 0.0 # Links new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) @@ -195,11 +865,13 @@ def make_uva4(): new_grp.links.new(grp_in.outputs[2], mult3.inputs[1]) new_grp.links.new(grp_in.outputs[3], mult4.inputs[1]) new_grp.links.new(grp_in.outputs[3], mult1.inputs[0]) - new_grp.links.new(grp_in.outputs[4], mult2.inputs[1]) + new_grp.links.new(grp_in.outputs[4], time_add.inputs[0]) + new_grp.links.new(time_add.outputs[0], mult2.inputs[1]) new_grp.links.new(mult1.outputs[0], mult2.inputs[0]) new_grp.links.new(mult2.outputs[0], mod1.inputs[0]) new_grp.links.new(mod1.outputs[0], mult3.inputs[0]) - new_grp.links.new(mult3.outputs[0], mult4.inputs[0]) + new_grp.links.new(mult3.outputs[0], floor.inputs[0]) + new_grp.links.new(floor.outputs[0], mult4.inputs[0]) new_grp.links.new(mult4.outputs[0], map1.inputs[0]) new_grp.links.new(map1.outputs[0], add1.inputs[0]) new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) @@ -236,7 +908,7 @@ def make_uva5(): # Modulo mod1 = new_grp.nodes.new('ShaderNodeMath') mod1.operation = 'MODULO' - mod1.inputs[1].default_value = 900.0 + mod1.inputs[1].default_value = 1.0 mod1.location = (-400, 0) # Multiply3 @@ -258,6 +930,19 @@ def make_uva5(): add1 = new_grp.nodes.new('ShaderNodeVectorMath') add1.operation = 'ADD' add1.location = (600, 0) + + # Timing Add + time_add = new_grp.nodes.new('ShaderNodeMath') + time_add.operation = 'ADD' + time_add.location = (-802, -180) + drv = time_add.inputs[1].driver_add('default_value') + drv.driver.expression = 'frame/60' + + # Floor + floor = new_grp.nodes.new('ShaderNodeMath') + floor.operation = 'FLOOR' + floor.location = (-204, -180) + floor.inputs[1].default_value = 0.0 # Links new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) @@ -265,11 +950,13 @@ def make_uva5(): new_grp.links.new(grp_in.outputs[2], mult3.inputs[1]) new_grp.links.new(grp_in.outputs[3], mult4.inputs[1]) new_grp.links.new(grp_in.outputs[3], mult1.inputs[0]) - new_grp.links.new(grp_in.outputs[4], mult2.inputs[1]) + new_grp.links.new(grp_in.outputs[4], time_add.inputs[0]) + new_grp.links.new(time_add.outputs[0], mult2.inputs[1]) new_grp.links.new(mult1.outputs[0], mult2.inputs[0]) new_grp.links.new(mult2.outputs[0], mod1.inputs[0]) new_grp.links.new(mod1.outputs[0], mult3.inputs[0]) - new_grp.links.new(mult3.outputs[0], mult4.inputs[0]) + new_grp.links.new(mult3.outputs[0], floor.inputs[0]) + new_grp.links.new(floor.outputs[0], mult4.inputs[0]) new_grp.links.new(mult4.outputs[0], map1.inputs[0]) new_grp.links.new(map1.outputs[0], add1.inputs[0]) new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) @@ -290,7 +977,7 @@ def make_uva6(): grp_out.location = (300, 0) # Geometry input - geom_in = new_grp.nodes.new('ShaderNodeGeometry') + geom_in = new_grp.nodes.new('ShaderNodeTexCoord') geom_in.location = (-300, 0) # Adder1 @@ -300,7 +987,7 @@ def make_uva6(): # Links new_grp.links.new(grp_in.outputs[0], adder1.inputs[0]) - new_grp.links.new(geom_in.outputs['Global'], adder1.inputs[1]) + new_grp.links.new(geom_in.outputs['Object'], adder1.inputs[1]) new_grp.links.new(adder1.outputs[0], grp_out.inputs[0]) # 7 - Mode Who Must Not Be Named @@ -321,7 +1008,7 @@ def make_uva7(): grp_out.location = (0, 0) # Geometry input - geom_in = new_grp.nodes.new('ShaderNodeGeometry') + geom_in = new_grp.nodes.new('ShaderNodeTexCoord') geom_in.location = (-1000, 0) # View flip @@ -382,7 +1069,7 @@ def make_uva7(): # Links new_grp.links.new(grp_in.outputs[0], add2.inputs[0]) - new_grp.links.new(geom_in.outputs['View'], view_flip.inputs[0]) + new_grp.links.new(geom_in.outputs['Window'], view_flip.inputs[0]) new_grp.links.new(view_flip.outputs[0], sep1.inputs[0]) new_grp.links.new(grp_in.outputs[1], comb2.inputs[0]) new_grp.links.new(grp_in.outputs[1], comb2.inputs[1]) @@ -850,6 +1537,8 @@ MP3_PASS_GROUPS = ( ) def make_master_shader_library(): + for shad in ROOT_SHADER_GROUPS: + shad() for uva in UV_ANIMATION_GROUPS: uva() for aPass in MP3_PASS_GROUPS: diff --git a/DataSpec/DNACommon/ANCS.cpp b/DataSpec/DNACommon/ANCS.cpp index 0b1ed8e7d..a1b2e651e 100644 --- a/DataSpec/DNACommon/ANCS.cpp +++ b/DataSpec/DNACommon/ANCS.cpp @@ -100,14 +100,9 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con "bpy.context.scene.name = '%s'\n" "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n" "\n" - "# Using 'Blender Game'\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" - "\n" "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" "\n" "actor_data = bpy.context.scene.hecl_sact_data\n" "arm_obj = None\n", @@ -143,7 +138,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con /* Attach CMDL to CINF */ os << "if obj.name not in bpy.context.scene.objects:\n" - " bpy.context.scene.objects.link(obj)\n" + " bpy.context.scene.collection.objects.link(obj)\n" "obj.parent = arm_obj\n" "obj.parent_type = 'ARMATURE'\n" "actor_subtype.linked_mesh = obj.name\n\n"; @@ -162,7 +157,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con /* Attach CMDL to CINF */ os << "if obj.name not in bpy.context.scene.objects:\n" - " bpy.context.scene.objects.link(obj)\n" + " bpy.context.scene.collection.objects.link(obj)\n" "obj.parent = arm_obj\n" "obj.parent_type = 'ARMATURE'\n" "overlay.linked_mesh = obj.name\n\n"; @@ -202,7 +197,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con /* Attach CMDL to CINF */ os << "if obj.name not in bpy.context.scene.objects:\n" - " bpy.context.scene.objects.link(obj)\n" + " bpy.context.scene.collection.objects.link(obj)\n" "obj.parent = arm_obj\n" "obj.parent_type = 'ARMATURE'\n" "attachment.linked_mesh = obj.name\n\n"; diff --git a/DataSpec/DNACommon/BabeDead.cpp b/DataSpec/DNACommon/BabeDead.cpp index b804470cb..6d3b8400a 100644 --- a/DataSpec/DNACommon/BabeDead.cpp +++ b/DataSpec/DNACommon/BabeDead.cpp @@ -18,42 +18,42 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi return; case BabeDeadLight::LightType::Directional: os.format( - "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n" + "lamp = bpy.data.lights.new('LAMP_%01u_%03u', 'SUN')\n" "lamp.color = (%f,%f,%f)\n" "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" "lamp_obj.rotation_mode = 'QUATERNION'\n" "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n" - "lamp.shadow_method = '%s'\n" + "lamp.use_shadow = %s\n" "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], light.direction.simd[0], - light.direction.simd[1], light.direction.simd[2], light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); + light.direction.simd[1], light.direction.simd[2], light.castShadows ? "True" : "False"); return; case BabeDeadLight::LightType::Custom: os.format( - "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'POINT')\n" + "lamp = bpy.data.lights.new('LAMP_%01u_%03u', 'POINT')\n" "lamp.color = (%f,%f,%f)\n" "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" "lamp.shadow_soft_size = 1.0\n" - "lamp.shadow_method = '%s'\n" + "lamp.use_shadow = %s\n" "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], - light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); + light.castShadows ? "True" : "False"); break; case BabeDeadLight::LightType::Spot: case BabeDeadLight::LightType::Spot2: os.format( - "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n" + "lamp = bpy.data.lights.new('LAMP_%01u_%03u', 'SPOT')\n" "lamp.color = (%f,%f,%f)\n" "lamp.spot_size = %.6g\n" "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" "lamp_obj.rotation_mode = 'QUATERNION'\n" "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n" "lamp.shadow_soft_size = 0.5\n" - "lamp.shadow_method = '%s'\n" + "lamp.use_shadow = %s\n" "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], zeus::degToRad(light.spotCutoff), light.direction.simd[0], light.direction.simd[1], light.direction.simd[2], - light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); + light.castShadows ? "True" : "False"); break; default: return; @@ -73,7 +73,7 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi "hue_sat_node.inputs[4].default_value = (%f,%f,%f,1.0)\n" "lamp.node_tree.links.new(hue_sat_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[0])\n" "lamp_obj.location = (%f,%f,%f)\n" - "bpy.context.scene.objects.link(lamp_obj)\n" + "bpy.context.scene.collection.objects.link(lamp_obj)\n" "\n", s, light.lightType, light.q / 8.f, light.color.simd[0], light.color.simd[1], light.color.simd[2], light.position.simd[0], light.position.simd[1], light.position.simd[2]); diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp index 095667d40..b1bb08582 100644 --- a/DataSpec/DNACommon/CMDL.cpp +++ b/DataSpec/DNACommon/CMDL.cpp @@ -80,15 +80,12 @@ void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const Material hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); hecl::SystemUTF8Conv resPathView(resPath); os.format( - "if '%s' in bpy.data.textures:\n" + "if '%s' in bpy.data.images:\n" " image = bpy.data.images['%s']\n" - " texture = bpy.data.textures[image.name]\n" "else:\n" " image = bpy.data.images.load('''//%s''')\n" " image.name = '%s'\n" - " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" - " texture.image = image\n" - "texmap_list.append(texture)\n" + "texmap_list.append(image)\n" "\n", texName.c_str(), texName.c_str(), resPathView.c_str(), texName.c_str()); } @@ -375,19 +372,13 @@ public: } }; -void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath, - bool solidShading) { +void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath) { os << "import math\n" "from mathutils import Vector\n" "\n" - "# Using 'Blender Game'\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" - "\n" "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" "\n" "def loop_from_facevert(bm, face, vert_idx):\n" " for loop in face.loops:\n" @@ -422,7 +413,7 @@ void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectP " if od_entry is None:\n" " bm_cpy = bm.copy()\n" " od_entry = {'material':mat_nr, 'bm':bm_cpy}\n" - " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context=3)\n" + " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context='FACES_ONLY')\n" " od_list.append(od_entry)\n" " od_entry['bm'].verts.ensure_lookup_table()\n" " verts = [od_entry['bm'].verts[i] for i in vert_indices]\n" @@ -469,13 +460,6 @@ void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectP " return result\n" "\n"; - if (solidShading) { - os << "for ar in bpy.context.screen.areas:\n" - " for sp in ar.spaces:\n" - " if sp.type == 'VIEW_3D':\n" - " sp.viewport_shade = 'SOLID'\n"; - } - /* Link master shader library */ os.format( "# Master shader library\n" @@ -486,26 +470,27 @@ void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectP } void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int meshIdx) { - if (meshIdx < 0) - os.format( - "mesh = bpy.data.meshes.new(bpy.context.scene.name)\n" - "obj = bpy.data.objects.new(mesh.name, mesh)\n" - "obj.show_transparent = True\n" - "bpy.context.scene.objects.link(obj)\n" - "mesh.hecl_material_count = %u\n", - matSetCount); - else - os.format( - "mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n" - "obj = bpy.data.objects.new(mesh.name, mesh)\n" - "obj.show_transparent = True\n" - "bpy.context.scene.objects.link(obj)\n" - "mesh.hecl_material_count = %u\n", - meshIdx, matSetCount); + os << "if 'Render' not in bpy.data.collections:\n" + " coll = bpy.data.collections.new('Render')\n" + " bpy.context.scene.collection.children.link(coll)\n" + "else:\n" + " coll = bpy.data.collections['Render']\n"; + if (meshIdx < 0) { + os << "mesh = bpy.data.meshes.new(bpy.context.scene.name)\n" + "obj = bpy.data.objects.new(mesh.name, mesh)\n" + "obj.show_transparent = True\n" + "coll.objects.link(obj)\n"; + os.format("mesh.hecl_material_count = %u\n", matSetCount); + } else { + os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n", meshIdx); + os << "obj = bpy.data.objects.new(mesh.name, mesh)\n" + "obj.show_transparent = True\n" + "coll.objects.link(obj)\n"; + os.format("mesh.hecl_material_count = %u\n", matSetCount); + } os << "mesh.use_auto_smooth = True\n" "mesh.auto_smooth_angle = math.pi\n" - "mesh.show_edge_sharp = True\n" "\n" "for material in materials:\n" " mesh.materials.append(material)\n" @@ -549,7 +534,7 @@ void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int "for v in bm.verts:\n" " if len(v.link_faces) == 0:\n" " verts_to_del.append(v)\n" - "bmesh.ops.delete(bm, geom=verts_to_del, context=1)\n" + "bmesh.ops.delete(bm, geom=verts_to_del, context='VERTS')\n" "\n" "for edge in bm.edges:\n" " if edge.is_manifold:\n" @@ -1037,7 +1022,7 @@ bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReade "bpy.context.scene.name = '%s'\n" "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n", pakRouter.getBestEntryName(entry).c_str()); - InitGeomBlenderContext(os, dataspec.getMasterShaderPath(), false); + InitGeomBlenderContext(os, dataspec.getMasterShaderPath()); MaterialSet::RegisterMaterialProps(os); os << "# Materials\n" @@ -1142,9 +1127,9 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath /* Build material sets */ std::vector matSets; +#if 0 matSets.reserve(mesh.materialSets.size()); { - hecl::Frontend::Frontend FE; for (const std::vector& mset : mesh.materialSets) { matSets.emplace_back(); MaterialSet& targetMSet = matSets.back(); @@ -1191,6 +1176,7 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath paddingSizes.push_back(secSz32 - secSz); } } +#endif /* Vertex Positions */ size_t secSz = mesh.pos.size() * 12; @@ -1435,44 +1421,24 @@ bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& in /* Build material sets */ std::vector matSets; matSets.reserve(mesh.materialSets.size()); - { - hecl::Frontend::Frontend FE; - for (const std::vector& mset : mesh.materialSets) { - matSets.emplace_back(); - MaterialSet& targetMSet = matSets.back(); - std::vector texPaths; - texPaths.reserve(mset.size() * 4); - for (const Material& mat : mset) { - for (const hecl::ProjectPath& path : mat.texs) { - bool found = false; - for (const hecl::ProjectPath& ePath : texPaths) { - if (path == ePath) { - found = true; - break; - } - } - if (!found) - texPaths.push_back(path); - } - } - size_t endOff = 0; - for (const Material& mat : mset) { - std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); - targetMSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); - targetMSet.materials.back().binarySize(endOff); - targetMSet.head.addMaterialEndOff(endOff); - } + for (const std::vector& mset : mesh.materialSets) { + matSets.emplace_back(); + MaterialSet& targetMSet = matSets.back(); - for (const hecl::ProjectPath& path : texPaths) - targetMSet.head.addTexture(path); - - size_t secSz = 0; - targetMSet.binarySize(secSz); - size_t secSz32 = ROUND_UP_32(secSz); - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + size_t endOff = 0; + for (const Material& mat : mset) { + ++targetMSet.materialCount; + targetMSet.materials.emplace_back(mat); + targetMSet.materials.back().binarySize(endOff); + targetMSet.materialEndOffs.push_back(endOff); } + + size_t secSz = 0; + targetMSet.binarySize(secSz); + size_t secSz32 = ROUND_UP_32(secSz); + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); } hecl::blender::HMDLBuffers bufs = mesh.getHMDLBuffers(false, poolSkinIndex); @@ -1614,10 +1580,8 @@ bool WriteMREASecs(std::vector>& secsOut, const hecl::Proje surfCount += mesh.surfaces.size(); surfToGlobalMats.reserve(surfCount); - hecl::Frontend::Frontend FE; size_t endOff = 0; std::vector texPaths; - std::vector setBackends; for (const Mesh& mesh : meshes) { if (mesh.materialSets.size()) { std::vector meshToGlobalMats; @@ -1630,28 +1594,24 @@ bool WriteMREASecs(std::vector>& secsOut, const hecl::Proje if (!newMat) continue; - for (const hecl::ProjectPath& path : mat.texs) { - bool found = false; - for (const hecl::ProjectPath& ePath : texPaths) { - if (path == ePath) { - found = true; - break; + for (const auto& chunk : mat.chunks) { + if (auto pass = chunk.get_if()) { + bool found = false; + for (const hecl::ProjectPath& ePath : texPaths) { + if (pass->tex == ePath) { + found = true; + break; + } } + if (!found) + texPaths.push_back(pass->tex); } - if (!found) - texPaths.push_back(path); } - std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); - hecl::Frontend::IR matIR = FE.compileSource(mat.source, diagName); - setBackends.emplace_back(); - hecl::Backend::GX& matGX = setBackends.back(); - matGX.reset(matIR, FE.getDiagnostics()); - auto lightmapped = mat.iprops.find("retro_lightmapped"); bool lm = lightmapped != mat.iprops.cend() && lightmapped->second != 0; - matSet.materials.emplace_back(matGX, mat.iprops, mat.texs, texPaths, mesh.colorLayerCount, lm, false); + matSet.materials.emplace_back(mat, texPaths, mesh.colorLayerCount, lm, false); matSet.materials.back().binarySize(endOff); matSet.head.addMaterialEndOff(endOff); @@ -1917,10 +1877,8 @@ bool WriteHMDLMREASecs(std::vector>& secsOut, const hecl::P surfCount += mesh.surfaces.size(); surfToGlobalMats.reserve(surfCount); - MaterialSet matSet; - hecl::Frontend::Frontend FE; + MaterialSet matSet = {}; size_t endOff = 0; - std::vector texPaths; for (const Mesh& mesh : meshes) { if (mesh.materialSets.size()) { std::vector meshToGlobalMats; @@ -1933,30 +1891,16 @@ bool WriteHMDLMREASecs(std::vector>& secsOut, const hecl::P if (!newMat) continue; - for (const hecl::ProjectPath& path : mat.texs) { - bool found = false; - for (const hecl::ProjectPath& ePath : texPaths) { - if (path == ePath) { - found = true; - break; - } - } - if (!found) - texPaths.push_back(path); - } - - std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); - matSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); + ++matSet.materialCount; + matSet.materials.emplace_back(mat); matSet.materials.back().binarySize(endOff); - matSet.head.addMaterialEndOff(endOff); + matSet.materialEndOffs.push_back(endOff); } for (const Mesh::Surface& surf : mesh.surfaces) surfToGlobalMats.push_back(meshToGlobalMats[surf.materialIdx]); } } - for (const hecl::ProjectPath& path : texPaths) - matSet.head.addTexture(path); size_t secSz = 0; matSet.binarySize(secSz); diff --git a/DataSpec/DNACommon/CMDL.hpp b/DataSpec/DNACommon/CMDL.hpp index 54513bd33..ddd520556 100644 --- a/DataSpec/DNACommon/CMDL.hpp +++ b/DataSpec/DNACommon/CMDL.hpp @@ -1,8 +1,6 @@ #pragma once #include "athena/FileWriter.hpp" -#include "hecl/Frontend.hpp" -#include "hecl/Backend/GX.hpp" #include "PAK.hpp" #include "GX.hpp" #include "TXTR.hpp" @@ -121,8 +119,7 @@ template void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, unsigned setIdx); -void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath, - bool solidShading); +void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath); void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int meshIdx); template diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt index 87aa843a3..cb96323a9 100644 --- a/DataSpec/DNACommon/CMakeLists.txt +++ b/DataSpec/DNACommon/CMakeLists.txt @@ -13,7 +13,7 @@ make_dnalist(liblist DNACommon set(DNACOMMON_SOURCES DNACommon.hpp DNACommon.cpp PAK.hpp PAK.cpp - GX.hpp + GX.hpp GX.cpp FSM2.hpp FSM2.cpp MLVL.hpp MLVL.cpp CMDL.cpp diff --git a/DataSpec/DNACommon/DeafBabe.cpp b/DataSpec/DNACommon/DeafBabe.cpp index 3ad8fcee9..623b3e439 100644 --- a/DataSpec/DNACommon/DeafBabe.cpp +++ b/DataSpec/DNACommon/DeafBabe.cpp @@ -75,18 +75,18 @@ void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, b " mat = material_dict[mat_name]\n" " col_mesh.materials.append(mat)\n" "\n" - "bpy.context.scene.objects.link(col_mesh_obj)\n" - "bpy.context.scene.objects.active = col_mesh_obj\n" + "if 'Collision' not in bpy.data.collections:\n" + " coll = bpy.data.collections.new('Collision')\n" + " bpy.context.scene.collection.children.link(coll)\n" + "else:\n" + " coll = bpy.data.collections['Collision']\n" + "coll.objects.link(col_mesh_obj)\n" + "bpy.context.view_layer.objects.active = col_mesh_obj\n" "bpy.ops.object.mode_set(mode='EDIT')\n" "bpy.ops.mesh.tris_convert_to_quads()\n" "bpy.ops.object.mode_set(mode='OBJECT')\n" - "bpy.context.scene.objects.active = None\n"; - if (!isDcln) - os << "col_mesh_obj.layers[1] = True\n" - "col_mesh_obj.layers[0] = False\n"; - - os << "col_mesh_obj.draw_type = 'SOLID'\n" - "col_mesh_obj.game.physics_type = 'STATIC'\n" + "bpy.context.view_layer.objects.active = None\n" + "col_mesh_obj.display_type = 'SOLID'\n" "\n"; } diff --git a/DataSpec/DNACommon/GX.cpp b/DataSpec/DNACommon/GX.cpp new file mode 100644 index 000000000..37206aeaa --- /dev/null +++ b/DataSpec/DNACommon/GX.cpp @@ -0,0 +1,18 @@ +#include "GX.hpp" + +namespace GX { + +template <> +void Color::Enumerate::Read>(typename Read::StreamT& reader) { + reader.readUBytesToBuf(&num, 4); +} +template <> +void Color::Enumerate::Write>(typename Write::StreamT& writer) { + writer.writeUBytes(reinterpret_cast(&num), 4); +} +template <> +void Color::Enumerate::BinarySize>(typename BinarySize::StreamT& s) { + s += 4; +} + +} \ No newline at end of file diff --git a/DataSpec/DNACommon/GX.hpp b/DataSpec/DNACommon/GX.hpp index 1cc035871..9d2e5b813 100644 --- a/DataSpec/DNACommon/GX.hpp +++ b/DataSpec/DNACommon/GX.hpp @@ -1,4 +1,296 @@ #pragma once +#include "athena/DNA.hpp" + +namespace GX { +enum AttrType { NONE, DIRECT, INDEX8, INDEX16 }; + +enum TevColorArg { + CC_CPREV = 0, + CC_APREV = 1, + CC_C0 = 2, + CC_A0 = 3, + CC_C1 = 4, + CC_A1 = 5, + CC_C2 = 6, + CC_A2 = 7, + CC_TEXC = 8, + CC_TEXA = 9, + CC_RASC = 10, + CC_RASA = 11, + CC_ONE = 12, + CC_HALF = 13, + CC_KONST = 14, + CC_ZERO = 15, +}; + +enum TevAlphaArg { + CA_APREV = 0, + CA_A0 = 1, + CA_A1 = 2, + CA_A2 = 3, + CA_TEXA = 4, + CA_RASA = 5, + CA_KONST = 6, + CA_ZERO = 7, +}; + +enum TevKColorSel { + TEV_KCSEL_8_8 = 0x00, + TEV_KCSEL_7_8 = 0x01, + TEV_KCSEL_6_8 = 0x02, + TEV_KCSEL_5_8 = 0x03, + TEV_KCSEL_4_8 = 0x04, + TEV_KCSEL_3_8 = 0x05, + TEV_KCSEL_2_8 = 0x06, + TEV_KCSEL_1_8 = 0x07, + + TEV_KCSEL_1 = TEV_KCSEL_8_8, + TEV_KCSEL_3_4 = TEV_KCSEL_6_8, + TEV_KCSEL_1_2 = TEV_KCSEL_4_8, + TEV_KCSEL_1_4 = TEV_KCSEL_2_8, + + TEV_KCSEL_K0 = 0x0C, + TEV_KCSEL_K1 = 0x0D, + TEV_KCSEL_K2 = 0x0E, + TEV_KCSEL_K3 = 0x0F, + TEV_KCSEL_K0_R = 0x10, + TEV_KCSEL_K1_R = 0x11, + TEV_KCSEL_K2_R = 0x12, + TEV_KCSEL_K3_R = 0x13, + TEV_KCSEL_K0_G = 0x14, + TEV_KCSEL_K1_G = 0x15, + TEV_KCSEL_K2_G = 0x16, + TEV_KCSEL_K3_G = 0x17, + TEV_KCSEL_K0_B = 0x18, + TEV_KCSEL_K1_B = 0x19, + TEV_KCSEL_K2_B = 0x1A, + TEV_KCSEL_K3_B = 0x1B, + TEV_KCSEL_K0_A = 0x1C, + TEV_KCSEL_K1_A = 0x1D, + TEV_KCSEL_K2_A = 0x1E, + TEV_KCSEL_K3_A = 0x1F +}; + +enum TevKAlphaSel { + TEV_KASEL_8_8 = 0x00, + TEV_KASEL_7_8 = 0x01, + TEV_KASEL_6_8 = 0x02, + TEV_KASEL_5_8 = 0x03, + TEV_KASEL_4_8 = 0x04, + TEV_KASEL_3_8 = 0x05, + TEV_KASEL_2_8 = 0x06, + TEV_KASEL_1_8 = 0x07, + + TEV_KASEL_1 = TEV_KASEL_8_8, + TEV_KASEL_3_4 = TEV_KASEL_6_8, + TEV_KASEL_1_2 = TEV_KASEL_4_8, + TEV_KASEL_1_4 = TEV_KASEL_2_8, + + TEV_KASEL_K0_R = 0x10, + TEV_KASEL_K1_R = 0x11, + TEV_KASEL_K2_R = 0x12, + TEV_KASEL_K3_R = 0x13, + TEV_KASEL_K0_G = 0x14, + TEV_KASEL_K1_G = 0x15, + TEV_KASEL_K2_G = 0x16, + TEV_KASEL_K3_G = 0x17, + TEV_KASEL_K0_B = 0x18, + TEV_KASEL_K1_B = 0x19, + TEV_KASEL_K2_B = 0x1A, + TEV_KASEL_K3_B = 0x1B, + TEV_KASEL_K0_A = 0x1C, + TEV_KASEL_K1_A = 0x1D, + TEV_KASEL_K2_A = 0x1E, + TEV_KASEL_K3_A = 0x1F +}; + +enum TevOp { + TEV_ADD = 0, + TEV_SUB = 1, + TEV_COMP_R8_GT = 8, + TEV_COMP_R8_EQ = 9, + TEV_COMP_GR16_GT = 10, + TEV_COMP_GR16_EQ = 11, + TEV_COMP_BGR24_GT = 12, + TEV_COMP_BGR24_EQ = 13, + TEV_COMP_RGB8_GT = 14, + TEV_COMP_RGB8_EQ = 15, + TEV_COMP_A8_GT = TEV_COMP_RGB8_GT, + TEV_COMP_A8_EQ = TEV_COMP_RGB8_EQ +}; + +enum TevBias { + TB_ZERO = 0, + TB_ADDHALF = 1, + TB_SUBHALF = 2, +}; + +enum TevScale { CS_SCALE_1 = 0, CS_SCALE_2 = 1, CS_SCALE_4 = 2, CS_DIVIDE_2 = 3 }; + +enum TexGenType { + TG_MTX3x4 = 0, + TG_MTX2x4, + TG_BUMP0, + TG_BUMP1, + TG_BUMP2, + TG_BUMP3, + TG_BUMP4, + TG_BUMP5, + TG_BUMP6, + TG_BUMP7, + TG_SRTG +}; + +enum TexGenSrc { + TG_POS = 0, + TG_NRM, + TG_BINRM, + TG_TANGENT, + TG_TEX0, + TG_TEX1, + TG_TEX2, + TG_TEX3, + TG_TEX4, + TG_TEX5, + TG_TEX6, + TG_TEX7, + TG_TEXCOORD0, + TG_TEXCOORD1, + TG_TEXCOORD2, + TG_TEXCOORD3, + TG_TEXCOORD4, + TG_TEXCOORD5, + TG_TEXCOORD6, + TG_COLOR0, + TG_COLOR1 +}; + +enum TexMtx { + TEXMTX0 = 30, + TEXMTX1 = 33, + TEXMTX2 = 36, + TEXMTX3 = 39, + TEXMTX4 = 42, + TEXMTX5 = 45, + TEXMTX6 = 48, + TEXMTX7 = 51, + TEXMTX8 = 54, + TEXMTX9 = 57, + IDENTITY = 60 +}; + +enum PTTexMtx { + PTTEXMTX0 = 64, + PTTEXMTX1 = 67, + PTTEXMTX2 = 70, + PTTEXMTX3 = 73, + PTTEXMTX4 = 76, + PTTEXMTX5 = 79, + PTTEXMTX6 = 82, + PTTEXMTX7 = 85, + PTTEXMTX8 = 88, + PTTEXMTX9 = 91, + PTTEXMTX10 = 94, + PTTEXMTX11 = 97, + PTTEXMTX12 = 100, + PTTEXMTX13 = 103, + PTTEXMTX14 = 106, + PTTEXMTX15 = 109, + PTTEXMTX16 = 112, + PTTEXMTX17 = 115, + PTTEXMTX18 = 118, + PTTEXMTX19 = 121, + PTIDENTITY = 125 +}; + +enum TevRegID { TEVPREV = 0, TEVREG0 = 1, TEVREG1 = 2, TEVREG2 = 3, TEVLAZY = 5 }; + +enum DiffuseFn { DF_NONE = 0, DF_SIGN, DF_CLAMP }; + +enum AttnFn { AF_SPEC = 0, AF_SPOT = 1, AF_NONE }; + +enum Primitive { + POINTS = 0xb8, + LINES = 0xa8, + LINESTRIP = 0xb0, + TRIANGLES = 0x90, + TRIANGLESTRIP = 0x98, + TRIANGLEFAN = 0xa0, + QUADS = 0x80 +}; + +enum ChannelID { + GX_COLOR0, + GX_COLOR1, + GX_ALPHA0, + GX_ALPHA1, + GX_COLOR0A0, + GX_COLOR1A1, + GX_COLOR_ZERO, + GX_ALPHA_BUMP, + GX_ALPHA_BUMPN, + GX_COLOR_NULL = 0xff +}; + +enum BlendFactor : uint16_t { + BL_ZERO, + BL_ONE, + BL_SRCCLR, + BL_INVSRCCLR, + BL_SRCALPHA, + BL_INVSRCALPHA, + BL_DSTALPHA, + BL_INVDSTALPHA +}; + +struct Color : athena::io::DNA { + union { + uint8_t color[4]; + uint32_t num = 0; + }; + Color() = default; + Color& operator=(const atVec4f& vec) { + athena::simd_floats f(vec.simd); + color[0] = uint8_t(std::min(std::max(f[0] * 255.f, 0.f), 255.f)); + color[1] = uint8_t(std::min(std::max(f[1] * 255.f, 0.f), 255.f)); + color[2] = uint8_t(std::min(std::max(f[2] * 255.f, 0.f), 255.f)); + color[3] = uint8_t(std::min(std::max(f[3] * 255.f, 0.f), 255.f)); + return *this; + } + Color& operator=(const atVec3f& vec) { + athena::simd_floats f(vec.simd); + color[0] = uint8_t(std::min(std::max(f[0] * 255.f, 0.f), 255.f)); + color[1] = uint8_t(std::min(std::max(f[1] * 255.f, 0.f), 255.f)); + color[2] = uint8_t(std::min(std::max(f[2] * 255.f, 0.f), 255.f)); + color[3] = 0xff; + return *this; + } + Color& operator=(uint8_t val) { + color[0] = val; + color[1] = val; + color[2] = val; + color[3] = val; + return *this; + } + atVec4f toVec4f() const { + atVec4f out; + athena::simd_floats f; + f[0] = color[0] / 255.f; + f[1] = color[1] / 255.f; + f[2] = color[2] / 255.f; + f[3] = color[3] / 255.f; + out.simd.copy_from(f); + return out; + } + Color(const atVec4f& vec) { *this = vec; } + Color(const atVec3f& vec) { *this = vec; } + Color(uint8_t val) { *this = val; } + bool operator==(const Color& other) const { return num == other.num; } + bool operator!=(const Color& other) const { return num != other.num; } + uint8_t operator[](size_t idx) const { return color[idx]; } + uint8_t& operator[](size_t idx) { return color[idx]; } + AT_DECL_EXPLICIT_DNA +}; + +} -#include "hecl/Backend/GX.hpp" -using GX = hecl::Backend::GX; diff --git a/DataSpec/DNACommon/MAPA.cpp b/DataSpec/DNACommon/MAPA.cpp index bf0dfee68..577f005bc 100644 --- a/DataSpec/DNACommon/MAPA.cpp +++ b/DataSpec/DNACommon/MAPA.cpp @@ -120,16 +120,9 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const "('MAPSTATIONORVISIT2', 'Map Station or Visit 2', 'Visible after Map Station or Visit', 4)]," "name='Retro: Map Object Visibility Mode')\n" "\n" - "for ar in bpy.context.screen.areas:\n" - " for sp in ar.spaces:\n" - " if sp.type == 'VIEW_3D':\n" - " sp.viewport_shade = 'SOLID'\n" - "\n" "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" "\n" "def add_triangle(bm, verts):\n" " verts = [bm.verts[vi] for vi in verts]\n" @@ -164,7 +157,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const moMP12->transformMtx[i].simd.copy_to(mtxF[i]); os.format( "obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" - "bpy.context.scene.objects.link(obj)\n" + "bpy.context.scene.collection.objects.link(obj)\n" "obj.retro_mappable_type = %d\n" "obj.retro_mapobj_vis_mode = '%s'\n" "obj.retro_mappable_sclyid = '0x%08X'\n" @@ -185,7 +178,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const moMP3->transformMtx[i].simd.copy_to(mtxF[i]); os.format( "obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" - "bpy.context.scene.objects.link(obj)\n" + "bpy.context.scene.collection.objects.link(obj)\n" "obj.retro_mappable_type = %d\n" "obj.retro_mapobj_vis_mode = '%s'\n" "obj.retro_mappable_sclyid = '0x%08X'\n" @@ -272,10 +265,9 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const } os << "mesh = bpy.data.meshes.new('MAP')\n" - "mesh.show_edge_seams = True\n" "obj = bpy.data.objects.new(mesh.name, mesh)\n" "bm.to_mesh(mesh)\n" - "bpy.context.scene.objects.link(obj)\n" + "bpy.context.scene.collection.objects.link(obj)\n" "bm.free()\n"; const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id); diff --git a/DataSpec/DNACommon/MAPU.cpp b/DataSpec/DNACommon/MAPU.cpp index ac5dc6324..384f4cc48 100644 --- a/DataSpec/DNACommon/MAPU.cpp +++ b/DataSpec/DNACommon/MAPU.cpp @@ -21,10 +21,8 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const "from mathutils import Matrix\n" "\n" "# Clear Scene\n" - "bpy.context.scene.camera = None\n" - "for ob in bpy.data.objects:\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" "\n" "bpy.types.Object.retro_mapworld_color = bpy.props.FloatVectorProperty(name='Retro: MapWorld Color'," " description='Sets map world color', subtype='COLOR', size=4, min=0.0, max=1.0)\n" @@ -53,7 +51,7 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const "wldObj.scale = mtxd[2]\n" "wldObj.retro_mapworld_color = (%f, %f, %f, %f)\n" "wldObj.retro_mapworld_path = '''%s'''\n" - "bpy.context.scene.objects.link(wldObj)\n", + "bpy.context.scene.collection.objects.link(wldObj)\n", wld.name.c_str(), wldXfF[0][0], wldXfF[0][1], wldXfF[0][2], wldXfF[0][3], wldXfF[1][0], wldXfF[1][1], wldXfF[1][2], wldXfF[1][3], wldXfF[2][0], wldXfF[2][1], wldXfF[2][2], wldXfF[2][3], hexColorF[0], hexColorF[1], hexColorF[2], hexColorF[3], path.getParentPath().getRelativePathUTF8().data()); @@ -70,7 +68,7 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const "obj.location = mtxd[0]\n" "obj.rotation_quaternion = mtxd[1]\n" "obj.scale = mtxd[2]\n" - "bpy.context.scene.objects.link(obj)\n" + "bpy.context.scene.collection.objects.link(obj)\n" "obj.parent = wldObj\n", wld.name.c_str(), idx++, hexXfF[0][0], hexXfF[0][1], hexXfF[0][2], hexXfF[0][3], hexXfF[1][0], hexXfF[1][1], hexXfF[1][2], hexXfF[1][3], hexXfF[2][0], hexXfF[2][1], hexXfF[2][2], hexXfF[2][3]); @@ -81,7 +79,6 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const " for area in screen.areas:\n" " for space in area.spaces:\n" " if space.type == 'VIEW_3D':\n" - " space.viewport_shade = 'SOLID'\n" " space.clip_end = 8000.0\n"; os.centerView(); diff --git a/DataSpec/DNACommon/MLVL.cpp b/DataSpec/DNACommon/MLVL.cpp index b31d9962e..982d147c3 100644 --- a/DataSpec/DNACommon/MLVL.cpp +++ b/DataSpec/DNACommon/MLVL.cpp @@ -18,18 +18,15 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const if (!conn.createBlend(blendPath, hecl::blender::BlendType::World)) return false; hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format( - "import bpy\n" - "import bmesh\n" - "from mathutils import Matrix\n" - "\n" - "bpy.context.scene.name = 'World'\n" - "\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n"); + os << "import bpy\n" + "import bmesh\n" + "from mathutils import Matrix\n" + "\n" + "bpy.context.scene.name = 'World'\n" + "\n" + "# Clear Scene\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n"; /* Insert area empties */ int areaIdx = 0; @@ -46,7 +43,7 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const "bm.to_mesh(box_mesh)\n" "bm.free()\n" "box = bpy.data.objects.new(box_mesh.name, box_mesh)\n" - "bpy.context.scene.objects.link(box)\n" + "bpy.context.scene.collection.objects.link(box)\n" "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" "mtxd = mtx.decompose()\n" "box.rotation_mode = 'QUATERNION'\n" @@ -78,7 +75,7 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n"; os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx); os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n" - "bpy.context.scene.objects.link(dockObj)\n" + "bpy.context.scene.collection.objects.link(dockObj)\n" "bm.to_mesh(dockMesh)\n" "bm.free()\n" "dockObj.parent = box\n"; diff --git a/DataSpec/DNACommon/PAK.cpp b/DataSpec/DNACommon/PAK.cpp index 2bf50a515..2e7946790 100644 --- a/DataSpec/DNACommon/PAK.cpp +++ b/DataSpec/DNACommon/PAK.cpp @@ -322,7 +322,7 @@ hecl::ProjectPath PAKRouter::getCooked(const EntryType* entry) const auto overrideSearch = m_overrideEntries.find(entry->id); if (overrideSearch != m_overrideEntries.end()) { return overrideSearch->second.getCookedPath(*m_dataSpec.overrideDataSpec( - overrideSearch->second, m_dataSpec.getDataSpecEntry(), hecl::blender::SharedBlenderToken)); + overrideSearch->second, m_dataSpec.getDataSpecEntry())); } const PAKType* pak = m_pak.get(); diff --git a/DataSpec/DNAMP1/CINF.cpp b/DataSpec/DNAMP1/CINF.cpp index db744ae08..6c9d27437 100644 --- a/DataSpec/DNAMP1/CINF.cpp +++ b/DataSpec/DNAMP1/CINF.cpp @@ -34,7 +34,7 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { for (atUint32 bid : boneIds) { for (const Name& name : names) { if (name.boneId == bid) { - os.format("obj.vertex_groups.new('%s')\n", name.name.c_str()); + os.format("obj.vertex_groups.new(name='%s')\n", name.name.c_str()); break; } } @@ -47,8 +47,8 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c os.format( "arm = bpy.data.armatures.new('CINF_%08X')\n" "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.objects.link(arm_obj)\n" - "bpy.context.scene.objects.active = arm_obj\n" + "bpy.context.scene.collection.objects.link(arm_obj)\n" + "bpy.context.view_layer.objects.active = arm_obj\n" "bpy.ops.object.mode_set(mode='EDIT')\n" "arm_bone_table = {}\n", cinfId.toUint32()); @@ -72,10 +72,9 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", getBoneNameFromId(bone.m_origBone.id)->c_str(), - rotMode); + os.format("arm_obj.pose.bones['%s'].rotation_mode = 'QUATERNION'\n", + getBoneNameFromId(bone.m_origBone.id)->c_str()); } std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return hecl::Format("CINF_%08X", cinfId.toUint32()); } diff --git a/DataSpec/DNAMP1/CMDL.cpp b/DataSpec/DNAMP1/CMDL.cpp index a7809800a..c39722b00 100644 --- a/DataSpec/DNAMP1/CMDL.cpp +++ b/DataSpec/DNAMP1/CMDL.cpp @@ -67,11 +67,12 @@ bool CMDL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat writer.writeString(boneName); writer.writeUint32Big(skinMesh.skins.size()); - for (const std::vector skin : skinMesh.skins) { - writer.writeUint32Big(skin.size()); - for (const DNACMDL::Mesh::SkinBind& bind : skin) { - writer.writeUint32Big(bind.boneIdx); - writer.writeFloatBig(bind.weight); + for (const auto& skin : skinMesh.skins) { + size_t numBinds = skinMesh.countSkinBinds(skin); + writer.writeUint32Big(numBinds); + for (size_t i = 0; i < numBinds; ++i) { + writer.writeUint32Big(skin[i].vg_idx); + writer.writeFloatBig(skin[i].weight); } writer.writeUint32Big(*vertCountIt++); } @@ -103,10 +104,11 @@ bool CMDL::HMDLCook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i /* CVirtualBone structure just like original (for CPU skinning) */ writer.writeUint32Big(mesh.skins.size()); for (auto& s : mesh.skins) { - writer.writeUint32Big(s.size()); - for (auto& b : s) { - writer.writeUint32Big(b.boneIdx); - writer.writeFloatBig(b.weight); + size_t numBinds = mesh.countSkinBinds(s); + writer.writeUint32Big(numBinds); + for (size_t i = 0; i < numBinds; ++i) { + writer.writeUint32Big(s[i].vg_idx); + writer.writeFloatBig(s[i].weight); } } diff --git a/DataSpec/DNAMP1/CMDLMaterials.cpp b/DataSpec/DNAMP1/CMDLMaterials.cpp index 6c102c1de..4d1e505a8 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.cpp +++ b/DataSpec/DNAMP1/CMDLMaterials.cpp @@ -36,34 +36,37 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t out.format( "# Texture\n" - "tex_uv_node = new_nodetree.nodes.new('ShaderNodeGeometry')\n" - "tex_uv_node.label = '%s'\n" - "tex_node = new_nodetree.nodes.new('ShaderNodeTexture')\n" + "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" "tex_node.label = '%s %u'\n" - "texture_nodes.append(tex_node)\n" - "gridder.place_node(tex_uv_node, 1)\n" - "gridder.place_node(tex_node, 1)\n" - "tex_uv_node.location[0] -= 120\n" - "tex_node.location[0] += 120\n" - "tex_node.location[1] += 176\n", - mtxLabel, texLabel, texIdx); + "texture_nodes.append(tex_node)\n", + texLabel, texIdx); if (texIdx != 0xff) - out.format("tex_node.texture = tex_maps[%u]\n", texIdx); + out.format("tex_node.image = tex_maps[%u]\n", texIdx); if (type == GX::TG_POS) - out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['View'], tex_node.inputs['Vector']))\n"); + out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Window'], tex_node.inputs['Vector']))\n"; else if (type == GX::TG_NRM) - out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n"); + out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n"; else if (type >= GX::TG_TEX0 && type <= GX::TG_TEX7) { uint8_t texIdx = type - GX::TG_TEX0; out.format( + "tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" - "tex_uv_node.uv_layer = 'UV_%u'\n", + "tex_uv_node.uv_map = 'UV_%u'\n", texIdx); } - out << "\n"; + out.format("tex_uv_node.label = '%s'\n", mtxLabel); + + out << "gridder.place_node(tex_uv_node, 0)\n" + "gridder.place_node(tex_node, 0)\n" + "tex_uv_node.location[0] -= 120\n" + "tex_node.location[0] += 120\n" + "tex_node.location[1] += 176\n" + "\n"; } void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, const float* vals) { @@ -242,466 +245,226 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx) { out.format( - "# KColor\n" - "kc_node = new_nodetree.nodes.new('ShaderNodeRGB')\n" - "kc_node.label = 'KColor %u'\n" - "kc_node.outputs['Color'].default_value[0] = %f\n" - "kc_node.outputs['Color'].default_value[1] = %f\n" - "kc_node.outputs['Color'].default_value[2] = %f\n" - "kc_node.outputs['Color'].default_value[3] = %f\n" - "gridder.place_node(kc_node, 1)\n" - "\n" - "ka_node = new_nodetree.nodes.new('ShaderNodeValue')\n" - "ka_node.label = 'KAlpha %u'\n" - "ka_node.outputs['Value'].default_value = %f\n" - "gridder.place_node(ka_node, 1)\n" - "\n" - "kcolor_nodes.append((kc_node,ka_node))\n" + "kcolors[%d] = (%f, %f, %f, %f)\n" + "kalphas[%d] = %f\n" "\n", idx, (float)col.color[0] / (float)0xff, (float)col.color[1] / (float)0xff, (float)col.color[2] / (float)0xff, (float)col.color[3] / (float)0xff, idx, (float)col.color[3] / (float)0xff); } -void Material::AddDynamicColor(Stream& out, unsigned idx) { - out.format( - "# Dynamic Color\n" - "node_name = 'DYNAMIC_C_%u'\n" - "if node_name not in new_nodetree.nodes:\n" - " dyn_c_node = new_nodetree.nodes.new('ShaderNodeRGB')\n" - " dyn_c_node.name = node_name\n" - " dyn_c_node.label = 'DYNAMIC_%u'\n" - " dyn_c_node.outputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n" - " gridder.place_node(dyn_c_node, 1)\n" - "\n", - idx, idx); +template +static uint32_t _HashTextureConfig(const MAT& mat) { + XXH32_state_t xxHash; + XXH32_reset(&xxHash, 0); + for (int i = 0; i < mat.tevStageCount; ++i) { + const auto& stage = mat.tevStages[i]; + XXH32_update(&xxHash, &stage.ciFlags, sizeof(stage.ciFlags)); + XXH32_update(&xxHash, &stage.aiFlags, sizeof(stage.aiFlags)); + XXH32_update(&xxHash, &stage.ccFlags, sizeof(stage.ccFlags)); + XXH32_update(&xxHash, &stage.acFlags, sizeof(stage.acFlags)); + XXH32_update(&xxHash, &stage.kaInput, sizeof(stage.kaInput)); + XXH32_update(&xxHash, &stage.kcInput, sizeof(stage.kcInput)); + XXH32_update(&xxHash, &stage.rascInput, sizeof(stage.rascInput)); + } + bool hasInd = mat.flags.samusReflectionIndirectTexture(); + XXH32_update(&xxHash, &hasInd, sizeof(hasInd)); + bool hasLm = mat.flags.lightmap(); + XXH32_update(&xxHash, &hasLm, sizeof(hasLm)); + return XXH32_digest(&xxHash); } -void Material::AddDynamicAlpha(Stream& out, unsigned idx) { - out.format( - "# Dynamic Alpha\n" - "node_name = 'DYNAMIC_A_%u'\n" - "if node_name not in new_nodetree.nodes:\n" - " dyn_a_node = new_nodetree.nodes.new('ShaderNodeValue')\n" - " dyn_a_node.name = node_name\n" - " dyn_a_node.label = 'DYNAMIC_%u'\n" - " dyn_a_node.outputs['Value'].default_value = 1.0\n" - " gridder.place_node(dyn_a_node, 1)\n" - "\n", - idx, idx); +static const char* ToString(GX::TevColorArg arg) { + switch (arg) { + case GX::CC_CPREV: + return "CC_CPREV"; + case GX::CC_APREV: + return "CC_APREV"; + case GX::CC_C0: + return "CC_C0"; + case GX::CC_A0: + return "CC_A0"; + case GX::CC_C1: + return "CC_C1"; + case GX::CC_A1: + return "CC_A1"; + case GX::CC_C2: + return "CC_C2"; + case GX::CC_A2: + return "CC_A2"; + case GX::CC_TEXC: + return "CC_TEXC"; + case GX::CC_TEXA: + return "CC_TEXA"; + case GX::CC_RASC: + return "CC_RASC"; + case GX::CC_RASA: + return "CC_RASA"; + case GX::CC_ONE: + return "CC_ONE"; + case GX::CC_HALF: + return "CC_HALF"; + case GX::CC_KONST: + return "CC_KONST"; + case GX::CC_ZERO: + return "CC_ZERO"; + default: + return "UNKNOWN"; + } } -enum class Combiner { Add, Sub, Mult }; -static void AddColorCombiner(Stream& out, Combiner type, const char* a, const char* b, const char* v) { - out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMixRGB')\n" - "combiner_node.inputs[0].default_value = 1.0\n" - "gridder.place_node_right(combiner_node, 2, 0)\n"; - if (type == Combiner::Add) - out << "combiner_node.blend_type = 'ADD'\n"; - else if (type == Combiner::Sub) - out << "combiner_node.blend_type = 'SUBTRACT'\n"; - else if (type == Combiner::Mult) - out << "combiner_node.blend_type = 'MULTIPLY'\n"; - - if (a) { - if (!strcmp(a, "ZERO")) - out << "combiner_node.inputs['Color1'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; - else if (!strcmp(a, "HALF")) - out << "combiner_node.inputs['Color1'].default_value = (0.5, 0.5, 0.5, 0.5)\n"; - else if (!strcmp(a, "ONE")) - out << "combiner_node.inputs['Color1'].default_value = (1.0, 1.0, 1.0, 1.0)\n"; - else if (!strcmp(a, "D0")) { - Material::AddDynamicColor(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], " - "combiner_node.inputs['Color1'])\n"; - } else if (!strcmp(a, "D1")) { - Material::AddDynamicColor(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], " - "combiner_node.inputs['Color1'])\n"; - } else if (!strcmp(a, "D2")) { - Material::AddDynamicColor(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], " - "combiner_node.inputs['Color1'])\n"; - } else if (!strlen(a)) { - } else - out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color1'])\n", a); +static const char* ToString(GX::TevAlphaArg arg) { + switch (arg) { + case GX::CA_APREV: + return "CA_APREV"; + case GX::CA_A0: + return "CA_A0"; + case GX::CA_A1: + return "CA_A1"; + case GX::CA_A2: + return "CA_A2"; + case GX::CA_TEXA: + return "CA_TEXA"; + case GX::CA_RASA: + return "CA_RASA"; + case GX::CA_KONST: + return "CA_KONST"; + case GX::CA_ZERO: + return "CA_ZERO"; + default: + return "UNKNOWN"; } - - if (b) { - if (!strcmp(b, "ZERO")) - out << "combiner_node.inputs['Color2'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; - else if (!strcmp(b, "HALF")) - out << "combiner_node.inputs['Color2'].default_value = (0.5, 0.5, 0.5, 0.5)\n"; - else if (!strcmp(b, "ONE")) - out << "combiner_node.inputs['Color2'].default_value = (1.0, 1.0, 1.0, 1.0)\n"; - else if (!strcmp(b, "D0")) { - Material::AddDynamicColor(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], " - "combiner_node.inputs['Color2'])\n"; - } else if (!strcmp(b, "D1")) { - Material::AddDynamicColor(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], " - "combiner_node.inputs['Color2'])\n"; - } else if (!strcmp(b, "D2")) { - Material::AddDynamicColor(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], " - "combiner_node.inputs['Color2'])\n"; - } else if (!strlen(b)) { - } else - out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color2'])\n", b); - } - - if (v) - out.format("new_nodetree.links.new(combiner_node.outputs['Color'], %s)\n", v); - - out << "color_combiner_sockets.append(combiner_node.outputs['Color'])\n\n"; } -static void AddAlphaCombiner(Stream& out, Combiner type, const char* a, const char* b, const char* v) { - out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMath')\n" - "gridder.place_node_right(combiner_node, 2, 1)\n"; - if (type == Combiner::Add) - out << "combiner_node.operation = 'ADD'\n"; - else if (type == Combiner::Sub) - out << "combiner_node.operation = 'SUBTRACT'\n"; - else if (type == Combiner::Mult) - out << "combiner_node.operation = 'MULTIPLY'\n"; - - if (a) { - if (!strcmp(a, "ZERO")) - out << "combiner_node.inputs[0].default_value = 0.0\n"; - else if (!strcmp(a, "HALF")) - out << "combiner_node.inputs[0].default_value = 0.5\n"; - else if (!strcmp(a, "ONE")) - out << "combiner_node.inputs[0].default_value = 1.0\n"; - else if (!strcmp(a, "D0")) { - Material::AddDynamicAlpha(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[0])\n"; - } else if (!strcmp(a, "D1")) { - Material::AddDynamicAlpha(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[0])\n"; - } else if (!strcmp(a, "D2")) { - Material::AddDynamicAlpha(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[0])\n"; - } else - out.format("new_nodetree.links.new(%s, combiner_node.inputs[0])\n", a); +static const char* ToString(GX::TevRegID arg) { + switch (arg) { + case GX::TEVPREV: + return "TEVPREV"; + case GX::TEVREG0: + return "TEVREG0"; + case GX::TEVREG1: + return "TEVREG1"; + case GX::TEVREG2: + return "TEVREG2"; + default: + return "UNKNOWN"; } - - if (b) { - if (!strcmp(b, "ZERO")) - out << "combiner_node.inputs[1].default_value = 0.0\n"; - else if (!strcmp(b, "HALF")) - out << "combiner_node.inputs[1].default_value = 0.5\n"; - else if (!strcmp(b, "ONE")) - out << "combiner_node.inputs[1].default_value = 1.0\n"; - else if (!strcmp(b, "D0")) { - Material::AddDynamicAlpha(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[1])\n"; - } else if (!strcmp(b, "D1")) { - Material::AddDynamicAlpha(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[1])\n"; - } else if (!strcmp(b, "D2")) { - Material::AddDynamicAlpha(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[1])\n"; - } else - out.format("new_nodetree.links.new(%s, combiner_node.inputs[1])\n", b); - } - - if (v) - out.format("new_nodetree.links.new(combiner_node.outputs[0], %s)\n", v); - - out << "alpha_combiner_sockets.append(combiner_node.outputs[0])\n\n"; -} - -static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg, GX::TevKColorSel kcolor, - const MaterialSet::Material::TEVStageTexInfo& stageTex, char c_regs[4][64], - char a_regs[4][64]) { - if (arg == GX::CC_ZERO) - strcpy(socketOut, "ZERO"); - else if (arg == GX::CC_HALF) - strcpy(socketOut, "HALF"); - else if (arg == GX::CC_ONE) - strcpy(socketOut, "ONE"); - else if (arg == GX::CC_TEXC) { - if (stageTex.tcgSlot == 0xff) - strcpy(socketOut, "ONE"); - else - sprintf(socketOut, "texture_nodes[%u].outputs['Color']", stageTex.tcgSlot); - } else if (arg == GX::CC_TEXA) { - if (stageTex.tcgSlot == 0xff) - strcpy(socketOut, "ONE"); - else - sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); - } else if (arg == GX::CC_RASC) - strcpy(socketOut, "material_node.outputs['Color']"); - else if (arg == GX::CC_RASA) - strcpy(socketOut, "material_node.outputs['Alpha']"); - else if (arg == GX::CC_KONST) { - int kreg = (kcolor - GX::TEV_KCSEL_K0) % 4; - if (kcolor < GX::TEV_KCSEL_K0) - strcpy(socketOut, "ONE"); - else if (kreg == 0) - strcpy(socketOut, "kcolor_nodes[0][0].outputs[0]"); - else if (kreg == 1) - strcpy(socketOut, "kcolor_nodes[1][0].outputs[0]"); - else if (kreg == 2) - strcpy(socketOut, "kcolor_nodes[2][0].outputs[0]"); - else if (kreg == 3) - strcpy(socketOut, "kcolor_nodes[3][0].outputs[0]"); - else - strcpy(socketOut, "ONE"); - } else if (arg == GX::CC_CPREV) - strcpy(socketOut, c_regs[GX::TEVPREV]); - else if (arg == GX::CC_APREV) - strcpy(socketOut, a_regs[GX::TEVPREV]); - else if (arg == GX::CC_C0) - strcpy(socketOut, c_regs[GX::TEVREG0]); - else if (arg == GX::CC_A0) - strcpy(socketOut, a_regs[GX::TEVREG0]); - else if (arg == GX::CC_C1) - strcpy(socketOut, c_regs[GX::TEVREG1]); - else if (arg == GX::CC_A1) - strcpy(socketOut, a_regs[GX::TEVREG1]); - else if (arg == GX::CC_C2) - strcpy(socketOut, c_regs[GX::TEVREG2]); - else if (arg == GX::CC_A2) - strcpy(socketOut, a_regs[GX::TEVREG2]); -} - -static void TranslateAlphaSocket(char* socketOut, GX::TevAlphaArg arg, GX::TevKAlphaSel kalpha, - const MaterialSet::Material::TEVStageTexInfo& stageTex, char a_regs[4][64]) { - if (arg == GX::CA_ZERO) - strcpy(socketOut, "ZERO"); - else if (arg == GX::CA_TEXA) { - if (stageTex.tcgSlot == 0xff) - strcpy(socketOut, "ONE"); - else - sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); - } else if (arg == GX::CA_RASA) - strcpy(socketOut, "material_node.outputs['Alpha']"); - else if (arg == GX::CA_KONST) { - int kreg = kalpha - GX::TEV_KASEL_K0_A; - if (kreg == 0) - strcpy(socketOut, "kcolor_nodes[0][1].outputs[0]"); - else if (kreg == 1) - strcpy(socketOut, "kcolor_nodes[1][1].outputs[0]"); - else if (kreg == 2) - strcpy(socketOut, "kcolor_nodes[2][1].outputs[0]"); - else if (kreg == 3) - strcpy(socketOut, "kcolor_nodes[3][1].outputs[0]"); - else - strcpy(socketOut, "ONE"); - } else if (arg == GX::CA_APREV) - strcpy(socketOut, a_regs[GX::TEVPREV]); - else if (arg == GX::CA_A0) - strcpy(socketOut, a_regs[GX::TEVREG0]); - else if (arg == GX::CA_A1) - strcpy(socketOut, a_regs[GX::TEVREG1]); - else if (arg == GX::CA_A2) - strcpy(socketOut, a_regs[GX::TEVREG2]); -} - -static void AddTEVStage(Stream& out, const MaterialSet::Material::TEVStage& stage, - const MaterialSet::Material::TEVStageTexInfo& stageTex, char c_regs[4][64], char a_regs[4][64], - unsigned& c_combiner_idx, unsigned& a_combiner_idx) { - char ca[64]; - char cb[64]; - char cc[64]; - char cd[64]; - TranslateColorSocket(ca, stage.colorInA(), stage.kColorIn(), stageTex, c_regs, a_regs); - TranslateColorSocket(cb, stage.colorInB(), stage.kColorIn(), stageTex, c_regs, a_regs); - TranslateColorSocket(cc, stage.colorInC(), stage.kColorIn(), stageTex, c_regs, a_regs); - TranslateColorSocket(cd, stage.colorInD(), stage.kColorIn(), stageTex, c_regs, a_regs); - - char aa[64]; - char ab[64]; - char ac[64]; - char ad[64]; - TranslateAlphaSocket(aa, stage.alphaInA(), stage.kAlphaIn(), stageTex, a_regs); - TranslateAlphaSocket(ab, stage.alphaInB(), stage.kAlphaIn(), stageTex, a_regs); - TranslateAlphaSocket(ac, stage.alphaInC(), stage.kAlphaIn(), stageTex, a_regs); - TranslateAlphaSocket(ad, stage.alphaInD(), stage.kAlphaIn(), stageTex, a_regs); - - /* Apply color optimizations */ - unsigned c_tev_opts = 0; - if (stage.colorInA() == GX::CC_ZERO || stage.colorInC() == GX::CC_ONE) - c_tev_opts |= 1; - if (stage.colorInB() == GX::CC_ZERO || stage.colorInC() == GX::CC_ZERO) - c_tev_opts |= 2; - if (c_tev_opts & 1 || c_tev_opts & 2) - c_tev_opts |= 4; - if (stage.colorInD() == GX::CC_ZERO || (c_tev_opts & 7) == 7) - c_tev_opts |= 8; - - /* Special A/D (additive) optimization */ - if (stage.colorInA() != GX::CC_ZERO && stage.colorInB() == GX::CC_ZERO && stage.colorInC() == GX::CC_ZERO && - stage.colorInD() != GX::CC_ZERO) { - c_tev_opts |= 0x1f; - AddColorCombiner(out, Combiner::Add, cd, ca, nullptr); - ++c_combiner_idx; - } else if (stage.colorInA() != GX::CC_ZERO && stage.colorInB() == GX::CC_ZERO && stage.colorInC() == GX::CC_ZERO && - stage.colorInD() == GX::CC_ZERO) { - c_tev_opts |= 0xf; - } else if (stage.colorInA() == GX::CC_ZERO && stage.colorInB() == GX::CC_ZERO && stage.colorInC() == GX::CC_ZERO && - stage.colorInD() != GX::CC_ZERO) { - c_tev_opts |= 0xf; - } - - if (!(c_tev_opts & 1)) { - /* A nodes */ - AddColorCombiner(out, Combiner::Sub, "ONE", ca, nullptr); - ++c_combiner_idx; - if (strcmp(cc, "ONE")) { - AddColorCombiner(out, Combiner::Mult, cc, "color_combiner_sockets[-1]", nullptr); - ++c_combiner_idx; - } - } - - const char* c_soc_log[2] = {"color_combiner_sockets[-1]", "color_combiner_sockets[-2]"}; - - if (!(c_tev_opts & 2)) { - /* B nodes */ - if (!strcmp(cc, "ONE")) { - if (strcmp(cb, "ZERO") && strcmp(cb, "HALF") && strcmp(cb, "ONE") && strcmp(cb, "D0") && strcmp(cb, "D1") && - strcmp(cb, "D2")) { - out.format("color_combiner_sockets.append(%s)\n", cb); - ++c_combiner_idx; - } else { - c_soc_log[1] = c_soc_log[0]; - c_soc_log[0] = cb; - } - } else { - AddColorCombiner(out, Combiner::Mult, cc, cb, nullptr); - ++c_combiner_idx; - } - } - - if (!(c_tev_opts & 4)) { - /* A+B node */ - AddColorCombiner(out, Combiner::Add, c_soc_log[0], c_soc_log[1], nullptr); - ++c_combiner_idx; - } - - if (!(c_tev_opts & 8)) { - /* +D node */ - AddColorCombiner(out, Combiner::Add, cd, c_soc_log[0], nullptr); - ++c_combiner_idx; - } - - /* Apply alpha optimizations */ - unsigned a_tev_opts = 0; - if (stage.alphaInA() == GX::CA_ZERO) - a_tev_opts |= 1; - if (stage.alphaInB() == GX::CA_ZERO || stage.alphaInC() == GX::CA_ZERO) - a_tev_opts |= 2; - if (a_tev_opts & 1 || a_tev_opts & 2) - a_tev_opts |= 4; - if (stage.alphaInD() == GX::CA_ZERO || (a_tev_opts & 7) == 7) - a_tev_opts |= 8; - - /* Special A/D (additive) optimization */ - if (stage.alphaInA() != GX::CA_ZERO && stage.alphaInB() == GX::CA_ZERO && stage.alphaInC() == GX::CA_ZERO && - stage.alphaInD() != GX::CA_ZERO) { - a_tev_opts |= 0x1f; - AddAlphaCombiner(out, Combiner::Add, ad, aa, nullptr); - ++a_combiner_idx; - } else if (stage.alphaInA() != GX::CA_ZERO && stage.alphaInB() == GX::CA_ZERO && stage.alphaInC() == GX::CA_ZERO && - stage.alphaInD() == GX::CA_ZERO) { - a_tev_opts |= 0xf; - } else if (stage.alphaInA() == GX::CA_ZERO && stage.alphaInB() == GX::CA_ZERO && stage.alphaInC() == GX::CA_ZERO && - stage.alphaInD() != GX::CA_ZERO) { - a_tev_opts |= 0xf; - } - - if (!(a_tev_opts & 1)) { - /* A nodes */ - AddAlphaCombiner(out, Combiner::Sub, "ONE", aa, nullptr); - ++a_combiner_idx; - if (strcmp(ac, "ONE")) { - AddAlphaCombiner(out, Combiner::Mult, ac, "alpha_combiner_sockets[-1]", nullptr); - ++a_combiner_idx; - } - } - - const char* a_soc_log[2] = {"alpha_combiner_sockets[-1]", "alpha_combiner_sockets[-2]"}; - - if (!(a_tev_opts & 2)) { - /* B nodes */ - if (!strcmp(ac, "ONE")) { - if (strcmp(ab, "ZERO") && strcmp(ab, "HALF") && strcmp(ab, "ONE") && strcmp(ab, "D0") && strcmp(ab, "D1") && - strcmp(ab, "D2")) { - out.format("alpha_combiner_sockets.append(%s)\n", ab); - ++a_combiner_idx; - } else { - a_soc_log[1] = a_soc_log[0]; - a_soc_log[0] = ab; - } - } else { - AddAlphaCombiner(out, Combiner::Mult, ac, ab, nullptr); - ++a_combiner_idx; - } - } - - if (!(a_tev_opts & 4)) { - /* A+B node */ - AddAlphaCombiner(out, Combiner::Add, a_soc_log[0], a_soc_log[1], nullptr); - ++a_combiner_idx; - } - - if (!(a_tev_opts & 8)) { - /* +D node */ - AddAlphaCombiner(out, Combiner::Add, ad, a_soc_log[0], nullptr); - ++a_combiner_idx; - } - - /* Update TEV regs */ - if (c_tev_opts == 0xf) { - if (stage.colorInD() != GX::CC_ZERO) - strncpy(c_regs[stage.colorOpOutReg()], cd, 64); - else if (stage.colorInA() != GX::CC_ZERO) - strncpy(c_regs[stage.colorOpOutReg()], ca, 64); - } else - snprintf(c_regs[stage.colorOpOutReg()], 64, "color_combiner_sockets[%u]", c_combiner_idx - 1); - if (a_tev_opts == 0xf) { - if (stage.alphaInD() != GX::CA_ZERO) - strncpy(a_regs[stage.alphaOpOutReg()], ad, 64); - else if (stage.alphaInA() != GX::CA_ZERO) - strncpy(a_regs[stage.alphaOpOutReg()], aa, 64); - } else - snprintf(a_regs[stage.alphaOpOutReg()], 64, "alpha_combiner_sockets[%u]", a_combiner_idx - 1); - - /* Row Break in gridder */ - out << "gridder.row_break(2)\n"; } template -void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, unsigned matIdx) { +static void _DescribeTEV(const MAT& mat) { + for (int i = 0; i < mat.tevStageCount; ++i) { + const auto& stage = mat.tevStages[i]; + fprintf(stderr, "A:%s B:%s C:%s D:%s -> %s | A:%s B:%s C:%s D:%s -> %s\n", + ToString(stage.colorInA()), ToString(stage.colorInB()), + ToString(stage.colorInC()), ToString(stage.colorInD()), ToString(stage.colorOpOutReg()), + ToString(stage.alphaInA()), ToString(stage.alphaInB()), + ToString(stage.alphaInC()), ToString(stage.alphaInD()), ToString(stage.alphaOpOutReg())); + } + bool hasInd = mat.flags.samusReflectionIndirectTexture(); + bool hasLm = mat.flags.lightmap(); + fprintf(stderr, "HasIndirect: %d HasLightmap: %d\n", hasInd, hasLm); +} + +struct TexLink { + const char* shaderInput; + int texidx; + bool alpha; + TexLink(const char* shaderInput, int texidx = -1, bool alpha = false) + : shaderInput(shaderInput), texidx(texidx), alpha(alpha) {} +}; + +struct ExtendedSpecularLink { + int texidx; + ExtendedSpecularLink(int texidx = -1) : texidx(texidx) {} +}; + +struct KColLink { + const char* shaderInput; + int kcidx; + bool alpha; + KColLink(const char* shaderInput, int kcidx = 0, bool alpha = false) + : shaderInput(shaderInput), kcidx(kcidx), alpha(alpha) {} +}; + +struct WhiteColorLink { + const char* shaderInput; + explicit WhiteColorLink(const char* shaderInput) + : shaderInput(shaderInput) {} +}; + +static void _GenerateRootShader(Stream& out, int) { + /* End of shader links */ +} + +template +static void _GenerateRootShader(Stream& out, int tidx, TexLink tex, Targs... args) { + int texIdx = tex.texidx == -1 ? tidx : tex.texidx; + out << "texture_nodes[" << texIdx << "].name = '" << tex.shaderInput << "'\n"; + out << "texture_nodes[" << texIdx << "].label = '" << tex.shaderInput << "'\n"; + out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['" << + (tex.alpha ? "Alpha" : "Color") << "'], node.inputs['" << tex.shaderInput << "'])\n"; + if (tex.texidx == -1) + ++tidx; + _GenerateRootShader(out, tidx, args...); +} + +template +static void _GenerateRootShader(Stream& out, int tidx, ExtendedSpecularLink tex, Targs... args) { + int texIdx = tex.texidx == -1 ? tidx : tex.texidx; + out << "texture_nodes[" << texIdx << "].name = 'Specular'\n"; + out << "texture_nodes[" << texIdx << "].label = 'Specular'\n"; + out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['Color'], node.inputs['Specular'])\n"; + out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['Alpha'], node.inputs['ExtendedSpecular'])\n"; + if (tex.texidx == -1) + ++tidx; + _GenerateRootShader(out, tidx, args...); +} + +template +static void _GenerateRootShader(Stream& out, int tidx, KColLink kcol, Targs... args) { + out << "node.inputs['" << kcol.shaderInput << "'].default_value = " << + (kcol.alpha ? "kalphas[" : "kcolors[") << kcol.kcidx << "]\n"; + _GenerateRootShader(out, tidx, args...); +} + +template +static void _GenerateRootShader(Stream& out, int tidx, WhiteColorLink wcol, Targs... args) { + out << "node.inputs['" << wcol.shaderInput << "'].default_value = (1.0, 1.0, 1.0, 1.0)\n"; + _GenerateRootShader(out, tidx, args...); +} + +template +static void _GenerateRootShader(Stream& out, const char* type, Targs... args) { + out << "node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + "node.name = 'Output'\n" + "node.node_tree = bpy.data.node_groups['" << type << "']\n" + "gridder.place_node(node, 1)\n"; + _GenerateRootShader(out, 0, args...); +} + +static TexLink operator "" _tex(const char* str, size_t) { return TexLink(str); } +static TexLink operator "" _texa(const char* str, size_t) { return TexLink(str, -1, true); } +static KColLink operator "" _kcol(const char* str, size_t) { return KColLink(str); } +static KColLink operator "" _kcola(const char* str, size_t) { return KColLink(str, 0, true); } + +template +static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, unsigned matIdx) { unsigned i; - out.format( - "new_material = bpy.data.materials.new('MAT_%u_%u')\n" - "new_material.use_shadows = True\n" - "new_material.use_transparent_shadows = True\n" - "new_material.diffuse_color = (1.0,1.0,1.0)\n" - "new_material.diffuse_intensity = 1.0\n" - "new_material.specular_intensity = 0.0\n" - "new_material.use_nodes = True\n" - "new_nodetree = new_material.node_tree\n" - "material_node = new_nodetree.nodes['Material']\n" - "final_node = new_nodetree.nodes['Output']\n" - "\n" - "gridder = hecl.Nodegrid(new_nodetree)\n" - "gridder.place_node(final_node, 3)\n" - "gridder.place_node(material_node, 0)\n" - "material_node.material = new_material\n" - "\n" - "texture_nodes = []\n" - "kcolor_nodes = []\n" - "color_combiner_sockets = []\n" - "alpha_combiner_sockets = []\n" - "tex_links = []\n" - "tev_reg_sockets = [None]*4\n" - "\n", - groupIdx, matIdx); + out.format("new_material = bpy.data.materials.new('MAT_%u_%u')\n", groupIdx, matIdx); + out << "new_material.use_fake_user = True\n" + "new_material.use_nodes = True\n" + "new_nodetree = new_material.node_tree\n" + "for n in new_nodetree.nodes:\n" + " new_nodetree.nodes.remove(n)\n" + "\n" + "gridder = hecl.Nodegrid(new_nodetree)\n" + "\n" + "texture_nodes = []\n" + "kcolors = {}\n" + "kalphas = {}\n" + "tex_links = []\n" + "\n"; /* Material Flags */ out.format( @@ -713,13 +476,13 @@ void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, uns "new_material.retro_shadow_occluder = %s\n" "new_material.retro_samus_reflection_indirect = %s\n" "new_material.retro_lightmapped = %s\n" - "new_material.game_settings.invisible = %s\n", + "new_material.diffuse_color = (1, 1, 1, %s)\n", material.flags.depthSorting() ? "True" : "False", material.flags.alphaTest() ? "True" : "False", material.flags.samusReflection() ? "True" : "False", material.flags.depthWrite() ? "True" : "False", material.flags.samusReflectionSurfaceEye() ? "True" : "False", material.flags.shadowOccluderMesh() ? "True" : "False", material.flags.samusReflectionIndirectTexture() ? "True" : "False", material.flags.lightmap() ? "True" : "False", - material.flags.shadowOccluderMesh() ? "True" : "False"); + material.flags.shadowOccluderMesh() ? "0" : "1"); /* Texture Indices */ out << "tex_maps = []\n"; @@ -737,21 +500,9 @@ void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, uns using BlendFactor = Material::BlendFactor; if (material.blendDstFac != BlendFactor::BL_ZERO) { if (material.blendDstFac == BlendFactor::BL_ONE) - out << "new_material.game_settings.alpha_blend = 'ADD'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; + out << "new_material.blend_method = 'ADD'\n"; else - out << "new_material.game_settings.alpha_blend = 'ALPHA'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; - } - - /* Color channels (for combining dynamic lighting) */ - for (const Material::ColorChannel& chan : material.colorChannels) { - if (!chan.lighting()) - out << "new_material.use_shadeless = True\n"; + out << "new_material.blend_method = 'BLEND'\n"; } /* Add texture maps/tcgs */ @@ -771,49 +522,142 @@ void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, uns } /* Indirect texture node */ - if (material.flags.samusReflectionIndirectTexture()) { + if (material.flags.samusReflectionIndirectTexture()) Material::AddTexture(out, GX::TexGenSrc::TG_POS, -1, material.indTexSlot[0], false); - out << "# Indirect Texture\n" - "ind_out = new_nodetree.nodes.new('ShaderNodeOutput')\n" - "gridder.place_node(ind_out, 3)\n" - "ind_out.name = 'IndirectOutput'\n" - "ind_out.label = 'Indirect'\n" - "new_nodetree.links.new(tex_node.outputs['Color'], ind_out.inputs['Color'])\n"; + + /* Select appropriate root shader and link textures */ + uint32_t hash = _HashTextureConfig(material); + switch (hash) { + case 0x0473AE40: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; + case 0x072D2CB3: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + case 0x0879D346: /* RetroShader: KColorDiffuse, Alpha=Texture */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex); break; + case 0x0DA256BB: /* Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + case 0x11C41DA4: /* RetroDynamicCharacterShader: Diffuse, DynamicMaskTex, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicCharacterShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0x1218F83E: /* RetroShader: ObjLightmap, Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 1, true)); break; + case 0x129B8578: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break; + case 0x15A3E6E5: /* RetroShader: Diffuse, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break; + case 0x1BEB3E15: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + case 0x2261E0EB: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0x239C7724: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break; + case 0x240C4C84: /* RetroShader: Lightmap, KColorDiffuse, Specular, Reflection, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + case 0x2523A379: /* RetroDynamicShader: Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0x25E85017: /* RetroShader: Lightmap, KColorDiffuse, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; + case 0x27FD5C6C: /* RetroShader: ObjLightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + case 0x2AD9F535: /* RetroShader: Emissive, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + case 0x2C9F5104: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + case 0x2D059429: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break; + case 0x30AC64BB: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break; + case 0x39BC4809: /* RetroDynamicShader: ObjLightmap*Dynamic, Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0x3BF97299: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break; + case 0x47ECF3ED: /* RetroShader: Diffuse, Specular, Reflection, Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex); break; + case 0x4BBDFFA6: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + case 0x4D4127A3: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + case 0x54A92F25: /* RetroShader: ObjLightmap, KColorDiffuse, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; + case 0x5A62D5F0: /* RetroShader: Lightmap, Diffuse, UnusedExtendedSpecular?, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + case 0x5CB59821: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break; + case 0x5D0F0069: /* RetroShader: Diffuse, Emissive, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); break; + case 0x5D80E53C: /* RetroShader: Emissive, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0x5F0AB0E9: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + case 0x5F189425: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break; + case 0x6601D113: /* RetroShader: Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Emissive"_tex); break; + case 0x694287FA: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + case 0x6D98D689: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Specular, Reflection, Alpha=KAlpha*Dynamic */ + _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + case 0x7252CB90: /* RetroShader: Lightmap, Diffuse, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break; + case 0x76BEA57E: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0, IndirectTex */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex); break; + case 0x7D6A4487: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true)); break; + case 0x84319328: /* RetroShader: Reflection, UnusedSpecular?, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex); break; + case 0x846215DA: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 0, true)); break; + case 0x957709F8: /* RetroShader: Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Emissive"_tex); break; + case 0x96ABB2D3: /* RetroShader: Lightmap, Diffuse, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + case 0x985A0B67: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + case 0x9B4453A2: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break; + case 0xA187C630: /* RetroShader: Diffuse, Emissive, UnusedReflection?, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + case 0xC138DCFA: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + case 0xC3C8B1C8: /* RetroShader: KColorDiffuse, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_kcola); break; + case 0xC689C8C6: /* RetroShader: Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 0, true)); break; + case 0xC6B18B28: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + case 0xCD92D4C5: /* RetroShader: Diffuse, Reflection, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola); break; + case 0xD73E7728: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + case 0xDB8F01AD: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, UnusedSpecular?, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break; + case 0xE6784B10: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 1, true)); break; + case 0xE68FF182: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0xEB4645CF: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Alpha=DiffuseAlpha*Dynamic */ + _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + case 0xECEF8D1F: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0xF1C26570: /* RetroShader: Lightmap, Diffuse, Specular, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + case 0xF559DB08: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0xF9324367: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; + case 0xFD95D7FD: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + default: + _DescribeTEV(material); + Log.report(logvisor::Fatal, "Unable to resolve shader hash %08X\n", hash); break; } - /* TEV-emulation combiner-node index context */ - unsigned c_combiner_idx = 0; - unsigned a_combiner_idx = 0; - - /* Initialze TEV register sockets */ - char c_regs[4][64] = {"ONE", "D0", "D1", "D2"}; - char a_regs[4][64] = {"ONE", "D0", "D1", "D2"}; - /* Has Lightmap? */ if (material.flags.lightmap()) { if (material.tevStageTexInfo[0].texSlot != 0xff) out << "new_material.hecl_lightmap = tex_maps[0].name\n" - "tex_maps[0].image.use_fake_user = True\n"; + "tex_maps[0].use_fake_user = True\n"; } - /* Add TEV stages */ - for (i = 0; i < material.tevStageCount; ++i) { - const Material::TEVStage& stage = material.tevStages[i]; - const Material::TEVStageTexInfo& stage_tex = material.tevStageTexInfo[i]; - AddTEVStage(out, stage, stage_tex, c_regs, a_regs, c_combiner_idx, a_combiner_idx); - } - - /* Connect final prev register */ - if (!strcmp(c_regs[GX::TEVPREV], "ONE")) - out << "final_node.inputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n"; - else - out.format("new_nodetree.links.new(%s, final_node.inputs['Color'])\n", c_regs[GX::TEVPREV]); - - if (!strcmp(a_regs[GX::TEVPREV], "ONE")) - out << "final_node.inputs['Alpha'].default_value = 1.0\n"; - else - out.format("new_nodetree.links.new(%s, final_node.inputs['Alpha'])\n", a_regs[GX::TEVPREV]); - /* Texmtx Animation Section */ i = 0; for (const Material::UVAnimation& anim : material.uvAnims) @@ -825,52 +669,55 @@ void MaterialSet::ConstructMaterial(Stream& out, const MaterialSet::Material& ma _ConstructMaterial(out, material, groupIdx, matIdx); } -MaterialSet::Material::Material(const hecl::Backend::GX& gx, const std::unordered_map& iprops, - const std::vector& texPathsIn, - std::vector& texPathsOut, int colorCount, bool lightmapUVs, - bool matrixSkinning) { +MaterialSet::Material::Material(const hecl::blender::Material& mat, + std::vector& texPathsOut, + int colorCount, bool lightmapUVs, bool matrixSkinning) { + /* TODO: Rewrite for new shader rep */ XXH32_state_t xxHash; XXH32_reset(&xxHash, 0); +#if 0 if (gx.m_kcolorCount) { flags.setKonstValuesEnabled(true); konstCount.push_back(gx.m_kcolorCount); } +#endif - auto search = iprops.find("retro_depth_sort"); - if (search != iprops.end()) + auto search = mat.iprops.find("retro_depth_sort"); + if (search != mat.iprops.end()) flags.setDepthSorting(search->second != 0); - search = iprops.find("retro_alpha_test"); - if (search != iprops.end()) - flags.setPunchthroughAlpha(search->second != 0); + search = mat.iprops.find("retro_alpha_test"); + if (search != mat.iprops.end()) + flags.setAlphaTest(search->second != 0); - search = iprops.find("retro_samus_reflection"); - if (search != iprops.end()) + search = mat.iprops.find("retro_samus_reflection"); + if (search != mat.iprops.end()) flags.setSamusReflection(search->second != 0); - search = iprops.find("retro_depth_write"); - if (search != iprops.end()) + search = mat.iprops.find("retro_depth_write"); + if (search != mat.iprops.end()) flags.setDepthWrite(search->second != 0); - search = iprops.find("retro_samus_reflection_persp"); - if (search != iprops.end()) + search = mat.iprops.find("retro_samus_reflection_persp"); + if (search != mat.iprops.end()) flags.setSamusReflectionSurfaceEye(search->second != 0); - search = iprops.find("retro_shadow_occluder"); - if (search != iprops.end()) + search = mat.iprops.find("retro_shadow_occluder"); + if (search != mat.iprops.end()) flags.setShadowOccluderMesh(search->second != 0); - search = iprops.find("retro_samus_reflection_indirect"); - if (search != iprops.end()) + search = mat.iprops.find("retro_samus_reflection_indirect"); + if (search != mat.iprops.end()) flags.setSamusReflectionIndirectTexture(search->second != 0); - search = iprops.find("retro_lightmapped"); - if (search != iprops.end()) + search = mat.iprops.find("retro_lightmapped"); + if (search != mat.iprops.end()) flags.setLightmap(search->second != 0); flags.setLightmapUVArray(lightmapUVs); +#if 0 atUint16 texFlags = 0; atUint16 tcgFlags = 0; tevStageTexInfo.reserve(gx.m_tevCount); @@ -1074,91 +921,71 @@ MaterialSet::Material::Material(const hecl::Backend::GX& gx, const std::unordere XXH32_update(&xxHash, &uvAnimsSize, sizeof(uvAnimsSize)); XXH32_update(&xxHash, &uvAnimsCount, sizeof(uvAnimsCount)); +#endif uniqueIdx = XXH32_digest(&xxHash); } -HMDLMaterialSet::Material::Material(hecl::Frontend::Frontend& FE, const std::string& diagName, - const hecl::blender::Material& mat, - const std::unordered_map& iprops, - const std::vector& texPaths) { - auto search = iprops.find("retro_depth_sort"); - if (search != iprops.end()) +HMDLMaterialSet::Material::Material(const hecl::blender::Material& mat) { + auto search = mat.iprops.find("retro_depth_sort"); + if (search != mat.iprops.end()) flags.setDepthSorting(search->second != 0); - search = iprops.find("retro_alpha_test"); - if (search != iprops.end()) - flags.setPunchthroughAlpha(search->second != 0); + search = mat.iprops.find("retro_alpha_test"); + if (search != mat.iprops.end()) + flags.setAlphaTest(search->second != 0); - search = iprops.find("retro_samus_reflection"); - if (search != iprops.end()) + search = mat.iprops.find("retro_samus_reflection"); + if (search != mat.iprops.end()) flags.setSamusReflection(search->second != 0); - search = iprops.find("retro_depth_write"); - if (search != iprops.end()) + search = mat.iprops.find("retro_depth_write"); + if (search != mat.iprops.end()) flags.setDepthWrite(search->second != 0); - search = iprops.find("retro_samus_reflection_persp"); - if (search != iprops.end()) + search = mat.iprops.find("retro_samus_reflection_persp"); + if (search != mat.iprops.end()) flags.setSamusReflectionSurfaceEye(search->second != 0); - search = iprops.find("retro_shadow_occluder"); - if (search != iprops.end()) + search = mat.iprops.find("retro_shadow_occluder"); + if (search != mat.iprops.end()) flags.setShadowOccluderMesh(search->second != 0); - search = iprops.find("retro_samus_reflection_indirect"); - if (search != iprops.end()) + search = mat.iprops.find("retro_samus_reflection_indirect"); + if (search != mat.iprops.end()) flags.setSamusReflectionIndirectTexture(search->second != 0); - search = iprops.find("retro_lightmapped"); - if (search != iprops.end()) + search = mat.iprops.find("retro_lightmapped"); + if (search != mat.iprops.end()) flags.setLightmap(search->second != 0); - for (const hecl::ProjectPath& path : mat.texs) { - size_t idx = 0; - for (const hecl::ProjectPath& tPath : texPaths) { - if (path == tPath) { - textureIdxs.push_back(idx); - ++textureCount; - break; - } - ++idx; - } + XXH64_state_t xxh; + XXH64_reset(&xxh, 0); + shaderType = mat.shaderType; + XXH64_update(&xxh, &shaderType, sizeof(shaderType)); + chunkCount = 0; + chunks.reserve(mat.chunks.size()); + for (const auto& chunk : mat.chunks) { + chunk.visit([this, &xxh](const auto& var) { + using T = std::decay_t; + chunks.push_back(Chunk::Build(T::variant_type(), var)); + var.hash(&xxh); + ++chunkCount; + }); } - + blendMode = mat.blendMode; + XXH64_update(&xxh, &blendMode, sizeof(blendMode)); + int hashFlags = 0; + if (flags.samusReflection()) + hashFlags |= 1; if (flags.samusReflectionIndirectTexture()) - indTexSlot.push_back(textureIdxs.size()); - - heclSource = mat.source; - heclIr = FE.compileSource(mat.source, diagName); - - uvAnimsSize = 4; - uvAnimsCount = 0; - for (const hecl::Frontend::IR::Instruction& inst : heclIr.m_instructions) { - if (inst.m_op != hecl::Frontend::IR::OpType::Call) - continue; - if (inst.m_call.m_name.compare("Texture")) - continue; - - const hecl::Frontend::IR::Instruction& sourceInst = inst.getChildInst(heclIr, 1); - if (sourceInst.m_op != hecl::Frontend::IR::OpType::Call) - continue; - if (sourceInst.m_call.m_name.compare(0, 11, "RetroUVMode")) - continue; - - std::vector gameArgs; - gameArgs.reserve(sourceInst.getChildCount() - 1); - for (int i = 1; i < sourceInst.getChildCount(); ++i) { - const hecl::Frontend::IR::Instruction& ci = sourceInst.getChildInst(heclIr, i); - gameArgs.push_back(ci.getImmVec()); - } - - ++uvAnimsCount; - uvAnims.emplace_back(sourceInst.m_call.m_name, gameArgs); - size_t tmpUvAnimsSize = uvAnimsSize; - uvAnims.back().binarySize(tmpUvAnimsSize); - uvAnimsSize = tmpUvAnimsSize; - } + hashFlags |= 2; + if (flags.depthWrite()) + hashFlags |= 4; + if (flags.alphaTest()) + hashFlags |= 8; + XXH64_update(&xxh, &hashFlags, sizeof(hashFlags)); + hash = XXH64_digest(&xxh); } MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction, const std::vector& gameArgs) { @@ -1236,6 +1063,25 @@ void MaterialSet::Material::UVAnimation::Enumerate(typename Op::StreamT& s) { AT_SPECIALIZE_DNA(MaterialSet::Material::UVAnimation) +template +void HMDLMaterialSet::Material::PASS::Enumerate(typename Op::StreamT& s) { + Do({"type"}, type, s); + Do({"texId"}, texId, s); + Do({"source"}, source, s); + Do({"uvAnimType"}, uvAnimType, s); + size_t uvParmCount = uvAnimParamsCount(); + for (size_t i = 0; i < uvParmCount; ++i) + Do({}, uvAnimParms[i], s); + Do({"alpha"}, alpha, s); +} + +AT_SPECIALIZE_DNA(HMDLMaterialSet::Material::PASS) + + +const char* HMDLMaterialSet::Material::PASS::DNAType() { + return "DataSpec::DNAMP1::HMDLMaterialSet::Material::PASS"; +} + } // namespace DataSpec::DNAMP1 namespace DataSpec::DNAMP2 { diff --git a/DataSpec/DNAMP1/CMDLMaterials.hpp b/DataSpec/DNAMP1/CMDLMaterials.hpp index f0b361513..bcc01c1f6 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.hpp +++ b/DataSpec/DNAMP1/CMDLMaterials.hpp @@ -4,6 +4,7 @@ #include "DataSpec/DNACommon/GX.hpp" #include "DataSpec/DNACommon/CMDL.hpp" #include "DNAMP1.hpp" +#include "hecl/Blender/Connection.hpp" namespace DataSpec::DNAMP1 { @@ -60,7 +61,7 @@ struct MaterialSet : BigDNA { flags |= atUint32(enabled) << 4; } bool alphaTest() const { return (flags & 0x20) != 0; } - void setPunchthroughAlpha(bool enabled) { + void setAlphaTest(bool enabled) { flags &= ~0x20; flags |= atUint32(enabled) << 5; } @@ -468,8 +469,8 @@ struct MaterialSet : BigDNA { static void AddDynamicAlpha(hecl::blender::PyOutStream& out, unsigned idx); Material() = default; - Material(const hecl::Backend::GX& gx, const std::unordered_map& iprops, - const std::vector& texPathsIn, std::vector& texPathsOut, + Material(const hecl::blender::Material& material, + std::vector& texPathsOut, int colorCount, bool lightmapUVs, bool matrixSkinning); }; Vector materials; @@ -528,29 +529,114 @@ struct HMDLMaterialSet : BigDNA { static constexpr bool OneSection() { return false; } AT_DECL_DNA - MaterialSet::MaterialSetHead head; + Value materialCount = 0; + Vector materialEndOffs; struct Material : BigDNA { AT_DECL_DNA MaterialSet::Material::Flags flags; - Value textureCount = 0; - Vector textureIdxs; + using BlendMaterial = hecl::blender::Material; - Vector indTexSlot; + struct PASS : hecl::TypedRecordBigDNA { + AT_DECL_EXPLICIT_DNA + Value type; + UniqueID32 texId; + Value source; + Value uvAnimType; + Value uvAnimParms[9] = {}; + Value alpha; + PASS() = default; + explicit PASS(const BlendMaterial::PASS& pass) + : type(pass.type), texId(pass.tex), source(pass.source), uvAnimType(pass.uvAnimType), alpha(pass.alpha) { + std::copy(pass.uvAnimParms.begin(), pass.uvAnimParms.end(), std::begin(uvAnimParms)); + } + bool shouldNormalizeUv() const { + switch (uvAnimType) { + case BlendMaterial::UVAnimType::MvInvNoTranslation: + case BlendMaterial::UVAnimType::MvInv: + case BlendMaterial::UVAnimType::Model: + case BlendMaterial::UVAnimType::CylinderEnvironment: + return true; + default: + return false; + } + } + size_t uvAnimParamsCount() const { + switch (uvAnimType) { + default: + return 0; + case BlendMaterial::UVAnimType::Scroll: + case BlendMaterial::UVAnimType::HStrip: + case BlendMaterial::UVAnimType::VStrip: + return 4; + case BlendMaterial::UVAnimType::Rotation: + case BlendMaterial::UVAnimType::CylinderEnvironment: + return 2; + case BlendMaterial::UVAnimType::Eight: + return 9; + } + } + }; + struct CLR : hecl::TypedRecordBigDNA { + AT_DECL_DNA + Value type; + Value color; + CLR() = default; + explicit CLR(const BlendMaterial::CLR& clr) : type(clr.type), color(clr.color.val) {} + }; + using Chunk = hecl::TypedVariantBigDNA; - Value uvAnimsSize = 4; - Value uvAnimsCount = 0; - Vector uvAnims; + static unsigned TexMapIdx(BlendMaterial::PassType type) { + switch (type) { + case BlendMaterial::PassType::Lightmap: + return 0; + case BlendMaterial::PassType::Diffuse: + return 1; + case BlendMaterial::PassType::Emissive: + return 2; + case BlendMaterial::PassType::Specular: + return 3; + case BlendMaterial::PassType::ExtendedSpecular: + return 4; + case BlendMaterial::PassType::Reflection: + return 5; + case BlendMaterial::PassType::Alpha: + return 6; + case BlendMaterial::PassType::IndirectTex: + return 7; + default: + assert(false && "Unknown pass type"); + return 0; + } + } - String<-1> heclSource; - hecl::Frontend::IR heclIr; + Value hash; + Value shaderType; + Value chunkCount; + Vector chunks; + Value blendMode = BlendMaterial::BlendMode::Opaque; + + std::pair + blendFactors() const { + switch (blendMode) { + case BlendMaterial::BlendMode::Opaque: + default: + return {hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::Zero}; + case BlendMaterial::BlendMode::Alpha: + return {hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha}; + case BlendMaterial::BlendMode::Additive: + return {hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One}; + } + } Material() = default; - Material(hecl::Frontend::Frontend& FE, const std::string& diagName, const hecl::blender::Material& mat, - const std::unordered_map& iprops, const std::vector& texPaths); + Material(const hecl::blender::Material& mat); }; - Vector materials; + Vector materials; }; } // namespace DataSpec::DNAMP1 + +AT_SPECIALIZE_TYPED_VARIANT_BIGDNA(DataSpec::DNAMP1::HMDLMaterialSet::Material::PASS, + DataSpec::DNAMP1::HMDLMaterialSet::Material::CLR) diff --git a/DataSpec/DNAMP1/DCLN.cpp b/DataSpec/DNAMP1/DCLN.cpp index 318c75cc8..ac5b61f5d 100644 --- a/DataSpec/DNAMP1/DCLN.cpp +++ b/DataSpec/DNAMP1/DCLN.cpp @@ -7,8 +7,8 @@ namespace DataSpec::DNAMP1 { void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const { os.format( "obj = bpy.data.objects.new('%s', None)\n" - "obj.empty_draw_type = 'CUBE'\n" - "bpy.context.scene.objects.link(obj)\n" + "obj.empty_display_type = 'CUBE'\n" + "bpy.context.scene.collection.objects.link(obj)\n" "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" "mtxd = mtx.decompose()\n" "obj.rotation_mode = 'QUATERNION'\n" @@ -27,29 +27,6 @@ void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const } #endif -template -void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) { - Do({"xf[0]"}, xf[0], s); - Do({"xf[1]"}, xf[1], s); - Do({"xf[2]"}, xf[2], s); - Do({"halfExtent"}, halfExtent, s); - Do({"isLeaf"}, isLeaf, s); - if (isLeaf) { - if (!leafData) - leafData.reset(new LeafData); - Do({"leafData"}, *leafData, s); - } else { - if (!left) - left.reset(new Node); - Do({"left"}, *left, s); - if (!right) - right.reset(new Node); - Do({"right"}, *right, s); - } -} - -AT_SPECIALIZE_DNA(DCLN::Collision::Node) - void DCLN::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName) { /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); @@ -60,10 +37,8 @@ void DCLN::sendToBlender(hecl::blender::Connection& conn, std::string_view entry "\n" "bpy.context.scene.name = '%s'\n" "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n", + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n", entryName.data()); DeafBabe::BlenderInit(os); diff --git a/DataSpec/DNAMP1/DCLN.hpp b/DataSpec/DNAMP1/DCLN.hpp index f5e96a411..1839b559b 100644 --- a/DataSpec/DNAMP1/DCLN.hpp +++ b/DataSpec/DNAMP1/DCLN.hpp @@ -91,4 +91,27 @@ struct DCLN : BigDNA { static bool Cook(const hecl::ProjectPath& outPath, const std::vector& meshes); }; +template +void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) { + Do({"xf[0]"}, xf[0], s); + Do({"xf[1]"}, xf[1], s); + Do({"xf[2]"}, xf[2], s); + Do({"halfExtent"}, halfExtent, s); + Do({"isLeaf"}, isLeaf, s); + if (isLeaf) { + if (!leafData) + leafData.reset(new LeafData); + Do({"leafData"}, *leafData, s); + } else { + if (!left) + left.reset(new Node); + Do({"left"}, *left, s); + if (!right) + right.reset(new Node); + Do({"right"}, *right, s); + } +} + +AT_SPECIALIZE_DNA(DCLN::Collision::Node) + } // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/DeafBabe.cpp b/DataSpec/DNAMP1/DeafBabe.cpp index f02ad9e11..b074ba4b9 100644 --- a/DataSpec/DNAMP1/DeafBabe.cpp +++ b/DataSpec/DNAMP1/DeafBabe.cpp @@ -25,12 +25,15 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) { " 'Organic':(0.19, 0.45, 0.2)}\n" "\n" "# Diffuse Color Maker\n" + "from mathutils import Color\n" "def make_color(index, mat_type, name):\n" " new_mat = bpy.data.materials.new(name)\n" " if mat_type in TYPE_COLORS:\n" - " new_mat.diffuse_color = TYPE_COLORS[mat_type]\n" + " new_mat.diffuse_color = TYPE_COLORS[mat_type] + (1.0,)\n" " else:\n" - " new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " col = Color()\n" + " col.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " new_mat.diffuse_color = tuple(col) + (1.0,)\n" " return new_mat\n" "\n" "bpy.types.Material.retro_unknown = bpy.props.BoolProperty(name='Retro: Unknown (U)')\n" @@ -189,8 +192,6 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) { " return len(material_index)-1\n" " else:\n" " mat = make_color(len(material_dict), mat_type, mat_name)\n" - " mat.diffuse_intensity = 1.0\n" - " mat.specular_intensity = 0.0\n" " mat.retro_unknown = ((data >> 0) & 1)\n" " mat.retro_surface_stone = ((data >> 1) & 1)\n" " mat.retro_surface_metal = ((data >> 2) & 1)\n" diff --git a/DataSpec/DNAMP1/FRME.cpp b/DataSpec/DNAMP1/FRME.cpp index 8b2cc4405..79cf99ca9 100644 --- a/DataSpec/DNAMP1/FRME.cpp +++ b/DataSpec/DNAMP1/FRME.cpp @@ -292,10 +292,8 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: os << "import bpy, math, bmesh\n" "from mathutils import Matrix, Quaternion\n" "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" "\n" "def duplicateObject(copy_obj):\n" " # Create new mesh\n" @@ -307,16 +305,14 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: " ob_new.scale = copy_obj.scale\n" " ob_new.location = copy_obj.location\n" " # Link new object to the given scene and select it\n" - " bpy.context.scene.objects.link(ob_new)\n" + " bpy.context.scene.collection.objects.link(ob_new)\n" " return ob_new\n"; os.format( "bpy.context.scene.name = '%s'\n" "bpy.context.scene.render.resolution_x = 640\n" "bpy.context.scene.render.resolution_y = 480\n" - "bpy.context.scene.render.engine = 'CYCLES'\n" "bpy.context.scene.world.use_nodes = True\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" "bg_node.inputs[1].default_value = 0.0\n", pakRouter.getBestEntryName(entry).c_str()); @@ -377,12 +373,11 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: default: { zeus::simd_floats colorF(w.header.color.simd); os.format( - "lamp = bpy.data.lamps.new(name='%s', type='POINT')\n" + "lamp = bpy.data.lights.new(name='%s', type='POINT')\n" "lamp.color = (%f, %f, %f)\n" - "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n" - "lamp.constant_coefficient = %f\n" - "lamp.linear_coefficient = %f\n" - "lamp.quadratic_coefficient = %f\n" + "lamp.hecl_falloff_constant = %f\n" + "lamp.hecl_falloff_linear = %f\n" + "lamp.hecl_falloff_quadratic = %f\n" "lamp.retro_light_angle_constant = %f\n" "lamp.retro_light_angle_linear = %f\n" "lamp.retro_light_angle_quadratic = %f\n" @@ -396,7 +391,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "lamp.spot_size = %f\n", info->cutoff); else if (info->type == LITEInfo::ELightType::Directional) - os << "lamp.type = 'HEMI'\n"; + os << "lamp.type = 'SUN'\n"; } } } @@ -433,14 +428,15 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: os.format( "material = bpy.data.materials.new('%s')\n" - "material.specular_intensity = 0.0\n" - "tex_slot = material.texture_slots.add()\n" - "tex_slot.texture = bpy.data.textures.new('%s', 'IMAGE')\n" - "tex_slot.texture.image = image\n" - "material.active_texture = tex_slot.texture\n" + "material.use_nodes = True\n" + "new_nodetree = material.node_tree\n" + "for n in new_nodetree.nodes:\n" + " new_nodetree.nodes.remove(n)\n" + "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" + "tex_node.image = image\n" "bm = bmesh.new()\n" "verts = []\n", - w.header.name.c_str(), w.header.name.c_str()); + w.header.name.c_str()); for (int i = 0; i < info->quadCoordCount; ++i) { int ti; @@ -511,12 +507,12 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: os << "print(obj.name)\n" "copy_obj = duplicateObject(obj)\n" "copy_obj.parent = frme_obj\n" - "copy_obj.hide = False\n"; + "copy_obj.hide_set(False)\n"; } else if (w.type == SBIG('CAMR')) { os << "bpy.context.scene.camera = frme_obj\n" "if 'Camera' in bpy.data.objects:\n" " cam = bpy.data.objects['Camera']\n" - " bpy.context.scene.objects.unlink(cam)\n" + " #bpy.context.scene.objects.unlink(cam)\n" " bpy.data.objects.remove(cam)\n"; } else if (w.type == SBIG('PANE')) { using PANEInfo = Widget::PANEInfo; @@ -611,9 +607,9 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "mtxd = mtx.decompose()\n" "frme_obj.rotation_mode = 'QUATERNION'\n" "frme_obj.location = mtxd[0]\n" - "frme_obj.rotation_quaternion = mtxd[1] * angle\n" + "frme_obj.rotation_quaternion = mtxd[1] @ angle\n" "frme_obj.scale = mtxd[2]\n" - "bpy.context.scene.objects.link(frme_obj)\n", + "bpy.context.scene.collection.objects.link(frme_obj)\n", xfMtxF[0][0], xfMtxF[0][1], xfMtxF[0][2], originF[0], xfMtxF[1][0], xfMtxF[1][1], xfMtxF[1][2], originF[1], xfMtxF[2][0], xfMtxF[2][1], xfMtxF[2][2], originF[2]); } diff --git a/DataSpec/DNAMP1/MLVL.cpp b/DataSpec/DNAMP1/MLVL.cpp index 3edd546c4..aaf9bc4e5 100644 --- a/DataSpec/DNAMP1/MLVL.cpp +++ b/DataSpec/DNAMP1/MLVL.cpp @@ -298,7 +298,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat areaOut.depLayers.push_back(areaOut.deps.size()); for (const std::pair& path : layer) { if (path.first) { - urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first, btok); + urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first); if (tag.id.IsValid()) { if (path.second) areaOut.lazyDeps.emplace_back(tag.id.Value(), tag.type); @@ -326,7 +326,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat layerResources.addSharedPath(path, false); for (const std::pair& path : layerResources.sharedPaths) { - urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first, btok); + urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first); if (tag.id.IsValid()) { if (path.second) areaOut.lazyDeps.emplace_back(tag.id.Value(), tag.type); @@ -337,7 +337,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat } hecl::ProjectPath pathPath(areaPath.getParentPath(), _SYS_STR("!path.blend")); - urde::SObjectTag pathTag = g_curSpec->buildTagFromPath(pathPath, btok); + urde::SObjectTag pathTag = g_curSpec->buildTagFromPath(pathPath); if (pathTag.id.IsValid()) { areaOut.deps.emplace_back(pathTag.id.Value(), pathTag.type); areaOut.lazyDeps.emplace_back(0, FOURCC('NONE')); @@ -369,7 +369,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat return true; } -bool MLVL::CookMAPW(const hecl::ProjectPath& outPath, const World& wld, hecl::blender::Token& btok) { +bool MLVL::CookMAPW(const hecl::ProjectPath& outPath, const World& wld) { std::vector mapaTags; mapaTags.reserve(wld.areas.size()); @@ -380,7 +380,7 @@ bool MLVL::CookMAPW(const hecl::ProjectPath& outPath, const World& wld, hecl::bl /* Area map */ hecl::ProjectPath mapPath(area.path, _SYS_STR("/!map.blend")); if (mapPath.isFile()) - mapaTags.push_back(g_curSpec->buildTagFromPath(mapPath, btok)); + mapaTags.push_back(g_curSpec->buildTagFromPath(mapPath)); } /* Write out MAPW */ diff --git a/DataSpec/DNAMP1/MLVL.hpp b/DataSpec/DNAMP1/MLVL.hpp index 0da794481..219cd44e0 100644 --- a/DataSpec/DNAMP1/MLVL.hpp +++ b/DataSpec/DNAMP1/MLVL.hpp @@ -136,7 +136,7 @@ struct MLVL : BigDNA { static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const World& wld, hecl::blender::Token& btok); - static bool CookMAPW(const hecl::ProjectPath& outPath, const World& wld, hecl::blender::Token& btok); + static bool CookMAPW(const hecl::ProjectPath& outPath, const World& wld); static bool CookSAVW(const hecl::ProjectPath& outPath, const World& wld); }; diff --git a/DataSpec/DNAMP1/MREA.cpp b/DataSpec/DNAMP1/MREA.cpp index d982ab2a1..c079a8b34 100644 --- a/DataSpec/DNAMP1/MREA.cpp +++ b/DataSpec/DNAMP1/MREA.cpp @@ -21,9 +21,7 @@ void MREA::ReadBabeDeadToBlender_1_2(hecl::blender::PyOutStream& os, athena::io: atUint32 bdMagic = rs.readUint32Big(); if (bdMagic != 0xBABEDEAD) Log.report(logvisor::Fatal, "invalid BABEDEAD magic"); - os << "bpy.context.scene.render.engine = 'CYCLES'\n" - "bpy.context.scene.world.use_nodes = True\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" + os << "bpy.context.scene.world.use_nodes = True\n" "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" "bg_node.inputs[1].default_value = 0.0\n"; for (atUint32 s = 0; s < 2; ++s) { @@ -127,10 +125,10 @@ static void OutputOctreeNode(hecl::blender::PyOutStream& os, athena::io::MemoryR zeus::CVector3f extent = aabb.extents(); os.format( "obj = bpy.data.objects.new('Leaf', None)\n" - "bpy.context.scene.objects.link(obj)\n" + "bpy.context.scene.collection.objects.link(obj)\n" "obj.location = (%f,%f,%f)\n" "obj.scale = (%f,%f,%f)\n" - "obj.empty_draw_type = 'CUBE'\n" + "obj.empty_display_type = 'CUBE'\n" "obj.layers[1] = True\n" "obj.layers[0] = False\n", pos.x, pos.y, pos.z, extent.x, extent.y, extent.z); @@ -168,10 +166,10 @@ static void OutputOctreeNode(hecl::blender::PyOutStream& os, athena::io::IStream zeus::CVector3f extent = aabb.extents(); os.format( "obj = bpy.data.objects.new('Leaf', None)\n" - "bpy.context.scene.objects.link(obj)\n" + "bpy.context.scene.collection.objects.link(obj)\n" "obj.location = (%f,%f,%f)\n" "obj.scale = (%f,%f,%f)\n" - "obj.empty_draw_type = 'CUBE'\n" + "obj.empty_display_type = 'CUBE'\n" "obj.layers[1] = True\n" "obj.layers[0] = False\n", pos.x, pos.y, pos.z, extent.x, extent.y, extent.z); @@ -199,22 +197,21 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format( - "import bpy\n" - "import bmesh\n" - "from mathutils import Vector\n" - "\n" - "bpy.context.scene.name = '%s'\n", + os << "import bpy\n" + "import bmesh\n" + "from mathutils import Vector\n" + "bpy.context.scene.render.fps = 60\n" + "\n"; + os.format("bpy.context.scene.name = '%s'\n", pakRouter.getBestEntryName(entry, false).c_str()); - DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); + DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath()); MaterialSet::RegisterMaterialProps(os); os << "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" - "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" + "\n" + "bpy.types.Light.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" + "bpy.types.Light.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" "bpy.types.Object.retro_disable_enviro_visor = bpy.props.BoolProperty(name='Retro: Disable in Combat/Scan " "Visor')\n" "bpy.types.Object.retro_disable_thermal_visor = bpy.props.BoolProperty(name='Retro: Disable in Thermal " @@ -310,11 +307,11 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: } /* Origins to center of mass */ - os << "bpy.context.scene.layers[1] = True\n" + os << "bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = False\n" "bpy.ops.object.select_by_type(type='MESH')\n" "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" "bpy.ops.object.select_all(action='DESELECT')\n" - "bpy.context.scene.layers[1] = False\n"; + "bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = True\n"; /* Link MLVL scene as background */ os.linkBackground("//../!world.blend", "World"); @@ -678,7 +675,7 @@ bool MREA::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat for (const DNACMDL::Mesh::Surface::Vert& vert : surf.verts) w.writeUint32Big(vert.iPos); const DNACMDL::Material& mat = mesh.materialSets[0][surf.materialIdx]; - w.writeBool(mat.transparent); + w.writeBool(mat.blendMode != DNACMDL::Material::BlendMode::Opaque); } } diff --git a/DataSpec/DNAMP1/PATH.cpp b/DataSpec/DNAMP1/PATH.cpp index d0403fc3e..de3d03073 100644 --- a/DataSpec/DNAMP1/PATH.cpp +++ b/DataSpec/DNAMP1/PATH.cpp @@ -14,10 +14,10 @@ static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus const zeus::CVector3f extent = aabb.extents(); os.format( "obj = bpy.data.objects.new('Leaf_%d', None)\n" - "bpy.context.scene.objects.link(obj)\n" + "bpy.context.scene.collection.objects.link(obj)\n" "obj.location = (%f,%f,%f)\n" "obj.scale = (%f,%f,%f)\n" - "obj.empty_draw_type = 'CUBE'\n" + "obj.empty_display_type = 'CUBE'\n" "obj.layers[1] = True\n" "obj.layers[0] = False\n", idx, pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); @@ -39,15 +39,15 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry "material_index = []\n" "def make_ground_material(idxMask):\n" " mat = bpy.data.materials.new('Ground %%X' %% idxMask)\n" - " mat.diffuse_color = (0.8, 0.460, 0.194)\n" + " mat.diffuse_color = (0.8, 0.460, 0.194, 1.0)\n" " return mat\n" "def make_flyer_material(idxMask):\n" " mat = bpy.data.materials.new('Flyer %%X' %% idxMask)\n" - " mat.diffuse_color = (0.016, 0.8, 0.8)\n" + " mat.diffuse_color = (0.016, 0.8, 0.8, 1.0)\n" " return mat\n" "def make_swimmer_material(idxMask):\n" " mat = bpy.data.materials.new('Swimmer %%X' %% idxMask)\n" - " mat.diffuse_color = (0.074, 0.293, 0.8)\n" + " mat.diffuse_color = (0.074, 0.293, 0.8, 1.0)\n" " return mat\n" "def select_material(meshIdxMask, meshTypeMask):\n" " key = (meshIdxMask, meshTypeMask)\n" @@ -71,10 +71,8 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry "\n" "bpy.context.scene.name = '%s'\n" "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" "\n" "bm = bmesh.new()\n" "height_lay = bm.faces.layers.float.new('Height')\n", @@ -109,11 +107,11 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry os.format("aabb = bpy.data.objects.new('AABB', None)\n" "aabb.location = (%f,%f,%f)\n" "aabb.scale = (%f,%f,%f)\n" - "aabb.empty_draw_type = 'CUBE'\n" - "bpy.context.scene.objects.link(aabb)\n" + "aabb.empty_display_type = 'CUBE'\n" + "bpy.context.scene.collection.objects.link(aabb)\n" "centr = bpy.data.objects.new('Center', None)\n" "centr.location = (%f,%f,%f)\n" - "bpy.context.scene.objects.link(centr)\n", + "bpy.context.scene.collection.objects.link(centr)\n", aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f, aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f, aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f, @@ -143,16 +141,10 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry " mat = material_dict[mat_name]\n" " path_mesh.materials.append(mat)\n" "\n" - "bpy.context.scene.objects.link(path_mesh_obj)\n" - "path_mesh_obj.draw_type = 'SOLID'\n" - "path_mesh_obj.game.physics_type = 'STATIC'\n" - "path_mesh_obj.layers[1] = True\n" + "bpy.context.scene.collection.objects.link(path_mesh_obj)\n" + "path_mesh_obj.display_type = 'SOLID'\n" "bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n" - "\n" - "for ar in bpy.context.screen.areas:\n" - " for sp in ar.spaces:\n" - " if sp.type == 'VIEW_3D':\n" - " sp.viewport_shade = 'SOLID'\n"; + "\n"; if (xf) { const zeus::CMatrix4f& w = *xf; diff --git a/DataSpec/DNAMP2/CINF.cpp b/DataSpec/DNAMP2/CINF.cpp index 8054c44c9..236fb8115 100644 --- a/DataSpec/DNAMP2/CINF.cpp +++ b/DataSpec/DNAMP2/CINF.cpp @@ -34,7 +34,7 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { for (atUint32 bid : boneIds) { for (const Name& name : names) { if (name.boneId == bid) { - os.format("obj.vertex_groups.new('%s')\n", name.name.c_str()); + os.format("obj.vertex_groups.new(name='%s')\n", name.name.c_str()); break; } } @@ -47,8 +47,8 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c os.format( "arm = bpy.data.armatures.new('CINF_%08X')\n" "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.objects.link(arm_obj)\n" - "bpy.context.scene.objects.active = arm_obj\n" + "bpy.context.scene.collection.objects.link(arm_obj)\n" + "bpy.context.view_layer.objects.active = arm_obj\n" "bpy.ops.object.mode_set(mode='EDIT')\n" "arm_bone_table = {}\n", cinfId.toUint32()); @@ -72,10 +72,9 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", getBoneNameFromId(bone.m_origBone.id)->c_str(), - rotMode); + os.format("arm_obj.pose.bones['%s'].rotation_mode = 'QUATERNION'\n", + getBoneNameFromId(bone.m_origBone.id)->c_str()); } std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return hecl::Format("CINF_%08X", cinfId.toUint32()); } diff --git a/DataSpec/DNAMP2/DeafBabe.cpp b/DataSpec/DNAMP2/DeafBabe.cpp index 995222068..344a060be 100644 --- a/DataSpec/DNAMP2/DeafBabe.cpp +++ b/DataSpec/DNAMP2/DeafBabe.cpp @@ -215,8 +215,6 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) { " return len(material_index)-1\n" " else:\n" " mat = make_color(len(material_dict), mat_type, mat_name)\n" - " mat.diffuse_intensity = 1.0\n" - " mat.specular_intensity = 0.0\n" " mat.retro_unknown = ((data >> 0) & 1)\n" " mat.retro_surface_stone = ((data >> 1) & 1)\n" " mat.retro_surface_metal = ((data >> 2) & 1)\n" diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index ec36bd9e5..70a230928 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -197,15 +197,14 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "\n" "bpy.context.scene.name = '%s'\n", pakRouter.getBestEntryName(entry, false).c_str()); - DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); + DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath()); MaterialSet::RegisterMaterialProps(os); os << "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" - "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" + "\n" + "bpy.types.Light.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" + "bpy.types.Light.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" "bpy.types.Object.retro_disable_enviro_visor = bpy.props.BoolProperty(name='Retro: Disable in Combat/Scan " "Visor')\n" "bpy.types.Object.retro_disable_thermal_visor = bpy.props.BoolProperty(name='Retro: Disable in Thermal " @@ -284,11 +283,11 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: drs.seek(secStart + head.secSizes[curSec++], athena::Begin); /* Origins to center of mass */ - os << "bpy.context.scene.layers[1] = True\n" + os << "bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = False\n" "bpy.ops.object.select_by_type(type='MESH')\n" "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" "bpy.ops.object.select_all(action='DESELECT')\n" - "bpy.context.scene.layers[1] = False\n"; + "bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = True\n"; os.centerView(); os.close(); diff --git a/DataSpec/DNAMP3/CINF.cpp b/DataSpec/DNAMP3/CINF.cpp index 0a51b4fcf..86a9a5cb7 100644 --- a/DataSpec/DNAMP3/CINF.cpp +++ b/DataSpec/DNAMP3/CINF.cpp @@ -9,8 +9,8 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& c os.format("arm = bpy.data.armatures.new('CINF_%016" PRIX64 "')\n" "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.objects.link(arm_obj)\n" - "bpy.context.scene.objects.active = arm_obj\n" + "bpy.context.scene.collection.objects.link(arm_obj)\n" + "bpy.context.view_layer.objects.active = arm_obj\n" "bpy.ops.object.mode_set(mode='EDIT')\n" "arm_bone_table = {}\n", cinfId.toUint64()); @@ -37,10 +37,9 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& c os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", getBoneNameFromId(bone.m_origBone.id)->c_str(), - rotMode); + os.format("arm_obj.pose.bones['%s'].rotation_mode = 'QUATERNION'\n", + getBoneNameFromId(bone.m_origBone.id)->c_str()); } std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId) { diff --git a/DataSpec/DNAMP3/CMDLMaterials.cpp b/DataSpec/DNAMP3/CMDLMaterials.cpp index 93fe5cc03..047695ac1 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.cpp +++ b/DataSpec/DNAMP3/CMDLMaterials.cpp @@ -87,8 +87,6 @@ void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter& pak "new_material.use_shadows = True\n" "new_material.use_transparent_shadows = True\n" "new_material.diffuse_color = (1.0,1.0,1.0)\n" - "new_material.diffuse_intensity = 1.0\n" - "new_material.specular_intensity = 0.0\n" "new_material.use_nodes = True\n" "new_nodetree = new_material.node_tree\n" "material_node = new_nodetree.nodes['Material']\n" @@ -112,22 +110,16 @@ void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter& pak out.format( "new_material.retro_alpha_test = %s\n" "new_material.retro_shadow_occluder = %s\n" - "new_material.game_settings.invisible = %s\n", + "new_material.diffuse_color = (1, 1, 1, %s)\n", material.header.flags.alphaTest() ? "True" : "False", material.header.flags.shadowOccluderMesh() ? "True" : "False", - material.header.flags.shadowOccluderMesh() ? "True" : "False"); + material.header.flags.shadowOccluderMesh() ? "0" : "1"); /* Blend factors */ if (material.header.flags.alphaBlending()) - out << "new_material.game_settings.alpha_blend = 'ALPHA'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; + out << "new_material.blend_method = 'BLEND'\n"; else if (material.header.flags.additiveBlending()) - out << "new_material.game_settings.alpha_blend = 'ADD'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; + out << "new_material.blend_method = 'ADD'\n"; /* Texmap list */ out << "tex_maps = []\n" diff --git a/DataSpec/DNAMP3/MREA.cpp b/DataSpec/DNAMP3/MREA.cpp index 349dcd261..5eea21396 100644 --- a/DataSpec/DNAMP3/MREA.cpp +++ b/DataSpec/DNAMP3/MREA.cpp @@ -43,9 +43,7 @@ void MREA::ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, athena::io::I atUint32 bdMagic = rs.readUint32Big(); if (bdMagic != 0xBABEDEAD) Log.report(logvisor::Fatal, "invalid BABEDEAD magic"); - os << "bpy.context.scene.render.engine = 'CYCLES'\n" - "bpy.context.scene.world.use_nodes = True\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" + os << "bpy.context.scene.world.use_nodes = True\n" "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" "bg_node.inputs[1].default_value = 0.0\n"; for (atUint32 s = 0; s < 4; ++s) { @@ -102,15 +100,14 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "\n" "bpy.context.scene.name = '%s'\n", pakRouter.getBestEntryName(entry, false).c_str()); - DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); + DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath()); MaterialSet::RegisterMaterialProps(os); os << "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" - "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" + "if 'Collection 1' in bpy.data.collections:\n" + " bpy.data.collections.remove(bpy.data.collections['Collection 1'])\n" + "\n" + "bpy.types.Light.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" + "bpy.types.Light.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" "\n"; /* One shared material set for all meshes */ @@ -213,11 +210,11 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: } /* Origins to center of mass */ - os << "bpy.context.scene.layers[1] = True\n" + os << "bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = False\n" "bpy.ops.object.select_by_type(type='MESH')\n" "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" "bpy.ops.object.select_all(action='DESELECT')\n" - "bpy.context.scene.layers[1] = False\n"; + "bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = True\n"; os.centerView(); os.close(); diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index fc4125777..fffacae8e 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -193,7 +193,7 @@ static bool IsPathSong(const hecl::ProjectPath& path) { return true; } -bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok, int cookPass) { +bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok) { if (!checkPathPrefix(path)) return false; @@ -205,16 +205,9 @@ bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok if (hecl::IsPathBlend(asBlend)) { hecl::blender::BlendType type = hecl::blender::GetBlendType(asBlend.getAbsolutePath()); - if (type != hecl::blender::BlendType::None) - return cookPass < 0 || (cookPass == 0 && type == hecl::blender::BlendType::Mesh) || // CMDL only - (cookPass == 1 && type != hecl::blender::BlendType::Mesh); // Non-CMDL only - return false; + return type != hecl::blender::BlendType::None; } - /* Non-CMDLs shall not pass */ - if (cookPass == 0) - return false; - if (hecl::IsPathPNG(path)) { return true; } else if (hecl::IsPathYAML(path)) { @@ -230,8 +223,7 @@ bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok } const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(const hecl::ProjectPath& path, - const hecl::Database::DataSpecEntry* oldEntry, - hecl::blender::Token& btok) const { + const hecl::Database::DataSpecEntry* oldEntry) const { if (!checkPathPrefix(path)) return nullptr; @@ -487,7 +479,7 @@ void SpecBase::recursiveBuildResourceList(std::vector& listOut if (hecl::ProjectPath(childPath, _SYS_STR("!project.yaml")).isFile() && hecl::ProjectPath(childPath, _SYS_STR("!pool.yaml")).isFile()) { /* Handle AudioGroup case */ - if (urde::SObjectTag tag = tagFromPath(childPath, btok)) { + if (urde::SObjectTag tag = tagFromPath(childPath)) { if (addedTags.find(tag) != addedTags.end()) continue; addedTags.insert(tag); @@ -501,7 +493,7 @@ void SpecBase::recursiveBuildResourceList(std::vector& listOut std::vector subPaths; flattenDependencies(childPath, subPaths, btok); for (const auto& subPath : subPaths) { - if (urde::SObjectTag tag = tagFromPath(subPath, btok)) { + if (urde::SObjectTag tag = tagFromPath(subPath)) { if (addedTags.find(tag) != addedTags.end()) continue; addedTags.insert(tag); @@ -637,7 +629,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da std::unordered_set addedTags; std::vector> nameList; for (const auto& subPath : subPaths) { - if (urde::SObjectTag tag = tagFromPath(subPath, btok)) { + if (urde::SObjectTag tag = tagFromPath(subPath)) { if (addedTags.find(tag) != addedTags.end()) continue; addedTags.insert(tag); @@ -664,21 +656,31 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da if (cp) { Log.report(logvisor::Info, _SYS_STR("Validating resources")); progress.setMainIndeterminate(true); - for (int i = 0; i < entry->m_numCookPasses; ++i) { + std::vector cookTags; + cookTags.reserve(buildList.size()); + + /* Ensure CMDLs are enqueued first to minimize synchronous dependency cooking */ + for (int i = 0; i < 2; ++i) { std::unordered_set addedTags; addedTags.reserve(buildList.size()); for (auto& tag : buildList) { - if (addedTags.find(tag) != addedTags.end()) - continue; - addedTags.insert(tag); - - hecl::ProjectPath depPath = pathFromTag(tag); - if (!depPath) { - Log.report(logvisor::Fatal, _SYS_STR("Unable to resolve %.4s %08X"), tag.type.getChars(), tag.id.Value()); + if ((i == 0 && tag.type == FOURCC('CMDL')) || + (i == 1 && tag.type != FOURCC('CMDL'))) { + if (addedTags.find(tag) != addedTags.end()) + continue; + addedTags.insert(tag); + cookTags.push_back(tag); } - m_project.cookPath(depPath, progress, false, false, fast, entry, cp, i); } } + + /* Cook ordered tags */ + for (auto& tag : cookTags) { + hecl::ProjectPath depPath = pathFromTag(tag); + if (!depPath) + Log.report(logvisor::Fatal, _SYS_STR("Unable to resolve %.4s %08X"), tag.type.getChars(), tag.id.Value()); + m_project.cookPath(depPath, progress, false, false, fast, entry, cp); + } progress.setMainIndeterminate(false); cp->waitUntilComplete(); progress.startNewLine(); @@ -699,7 +701,7 @@ void SpecBase::interruptCook() { cancelBackgroundIndex(); } hecl::ProjectPath SpecBase::getCookedPath(const hecl::ProjectPath& working, bool pcTarget) const { const hecl::Database::DataSpecEntry* spec = &getOriginalSpec(); if (pcTarget) - spec = overrideDataSpec(working, getDataSpecEntry(), hecl::blender::SharedBlenderToken); + spec = overrideDataSpec(working, getDataSpecEntry()); if (!spec) return {}; return working.getCookedPath(*spec); @@ -771,11 +773,11 @@ hecl::ProjectPath SpecBase::pathFromTag(const urde::SObjectTag& tag) const { return {}; } -urde::SObjectTag SpecBase::tagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { +urde::SObjectTag SpecBase::tagFromPath(const hecl::ProjectPath& path) const { auto search = m_pathToTag.find(path.hash()); if (search != m_pathToTag.cend()) return search->second; - return buildTagFromPath(path, btok); + return buildTagFromPath(path); } bool SpecBase::waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) { @@ -920,7 +922,7 @@ void SpecBase::readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAM } if (path.isNone()) continue; - urde::SObjectTag pathTag = tagFromPath(path, m_backgroundBlender); + urde::SObjectTag pathTag = tagFromPath(path); if (pathTag) { std::unique_lock lk(m_backgroundIndexMutex); m_catalogNameToTag[pLower] = pathTag; @@ -981,7 +983,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc return true; /* Classify intermediate into tag */ - urde::SObjectTag pathTag = buildTagFromPath(path, m_backgroundBlender); + urde::SObjectTag pathTag = buildTagFromPath(path); if (pathTag) { std::unique_lock lk(m_backgroundIndexMutex); bool useGlob = false; @@ -1004,7 +1006,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc for (const std::string& arm : armatureNames) { hecl::SystemStringConv sysStr(arm); hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".CINF")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + urde::SObjectTag pathTag = buildTagFromPath(subPath); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; WriteTag(cacheWriter, pathTag, subPath); @@ -1016,7 +1018,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc for (const std::string& sub : subtypeNames) { hecl::SystemStringConv sysStr(sub); hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".CSKR")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + urde::SObjectTag pathTag = buildTagFromPath(subPath); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; WriteTag(cacheWriter, pathTag, subPath); @@ -1029,7 +1031,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc hecl::SystemStringConv overlaySys(overlay); hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR('.') + overlaySys.c_str() + _SYS_STR(".CSKR")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + urde::SObjectTag pathTag = buildTagFromPath(subPath); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; WriteTag(cacheWriter, pathTag, subPath); @@ -1044,7 +1046,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc hecl::SystemStringConv attachmentSys(attachment); hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(_SYS_STR("ATTACH.")) + attachmentSys.c_str() + _SYS_STR(".CSKR")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + urde::SObjectTag pathTag = buildTagFromPath(subPath); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; WriteTag(cacheWriter, pathTag, subPath); @@ -1056,7 +1058,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc for (const std::string& act : actionNames) { hecl::SystemStringConv sysStr(act); hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".ANIM")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + urde::SObjectTag pathTag = buildTagFromPath(subPath); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; WriteTag(cacheWriter, pathTag, subPath); @@ -1070,7 +1072,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc useGlob = true; hecl::ProjectPath subPath = asGlob.ensureAuxInfo(_SYS_STR("MAPW")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + urde::SObjectTag pathTag = buildTagFromPath(subPath); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; WriteTag(cacheWriter, pathTag, subPath); @@ -1079,7 +1081,7 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc #endif subPath = asGlob.ensureAuxInfo(_SYS_STR("SAVW")); - pathTag = buildTagFromPath(subPath, m_backgroundBlender); + pathTag = buildTagFromPath(subPath); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; WriteTag(cacheWriter, pathTag, subPath); @@ -1216,7 +1218,7 @@ void SpecBase::backgroundIndexProc() { /* Add special original IDs resource if exists (not name-cached to disk) */ hecl::ProjectPath oidsPath(specRoot, "!original_ids.yaml"); - urde::SObjectTag oidsTag = buildTagFromPath(oidsPath, m_backgroundBlender); + urde::SObjectTag oidsTag = buildTagFromPath(oidsPath); if (oidsTag) { m_catalogNameToTag["mp1originalids"] = oidsTag; m_catalogTagToNames[oidsTag].insert("MP1OriginalIDs"); diff --git a/DataSpec/SpecBase.hpp b/DataSpec/SpecBase.hpp index f76130dda..5f64a7ebd 100644 --- a/DataSpec/SpecBase.hpp +++ b/DataSpec/SpecBase.hpp @@ -36,10 +36,9 @@ struct SpecBase : hecl::Database::IDataSpec { bool canExtract(const ExtractPassInfo& info, std::vector& reps); void doExtract(const ExtractPassInfo& info, const hecl::MultiProgressPrinter& progress); - bool canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok, int cookPass); + bool canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok); const hecl::Database::DataSpecEntry* overrideDataSpec(const hecl::ProjectPath& path, - const hecl::Database::DataSpecEntry* oldEntry, - hecl::blender::Token& btok) const; + const hecl::Database::DataSpecEntry* oldEntry) const; void doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, bool fast, hecl::blender::Token& btok, FCookProgress progress); @@ -59,7 +58,7 @@ struct SpecBase : hecl::Database::IDataSpec { virtual bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) = 0; /* Convert path to object tag */ - virtual urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const = 0; + virtual urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path) const = 0; /* Even if PC spec is being cooked, this will return the vanilla GCN spec */ virtual const hecl::Database::DataSpecEntry& getOriginalSpec() const = 0; @@ -145,7 +144,7 @@ struct SpecBase : hecl::Database::IDataSpec { void extractRandomStaticEntropy(const uint8_t* buf, const hecl::ProjectPath& noAramPath); /* Tag cache functions */ - urde::SObjectTag tagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const; + urde::SObjectTag tagFromPath(const hecl::ProjectPath& path) const; hecl::ProjectPath pathFromTag(const urde::SObjectTag& tag) const; bool waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut); const urde::SObjectTag* getResourceIdByName(std::string_view name) const; diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index a94c22363..51899ad36 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -480,7 +480,7 @@ struct SpecMP1 : SpecBase { }); } - urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { + urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path) const { if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CINF"))) return {SBIG('CINF'), path.hash().val32()}; else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR"))) @@ -655,9 +655,7 @@ struct SpecMP1 : SpecBase { void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, hecl::blender::Token& btok, FCookProgress progress) { - Mesh mesh = - ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, m_pc ? 16 : -1, - [&progress](int surfCount) { progress(hecl::SysFormat(_SYS_STR("%d"), surfCount).c_str()); }); + Mesh mesh = ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, m_pc ? 16 : -1); if (m_pc) DNAMP1::CMDL::HMDLCook(out, in, mesh); @@ -747,8 +745,7 @@ struct SpecMP1 : SpecBase { continue; } meshCompiles.push_back(ds.compileMesh( - mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1, !m_pc, - [&](int surfCount) { progress(hecl::SysFormat(_SYS_STR("%s %d"), meshSys.c_str(), surfCount).c_str()); })); + mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1, !m_pc)); } if (!colMesh) @@ -773,7 +770,7 @@ struct SpecMP1 : SpecBase { if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR("MAPW"))) { hecl::blender::World world = ds.compileWorld(); ds.close(); - DNAMP1::MLVL::CookMAPW(out, world, btok); + DNAMP1::MLVL::CookMAPW(out, world); } else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR("SAVW"))) { hecl::blender::World world = ds.compileWorld(); ds.close(); @@ -1028,7 +1025,7 @@ struct SpecMP1 : SpecBase { } listOut.reserve(count); - urde::SObjectTag worldTag = tagFromPath(worldPath.getWithExtension(_SYS_STR(".*"), true), btok); + urde::SObjectTag worldTag = tagFromPath(worldPath.getWithExtension(_SYS_STR(".*"), true)); w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005); w.writeUint32Big(0); @@ -1131,7 +1128,7 @@ struct SpecMP1 : SpecBase { auto data = btok.getBlenderConnection().beginData(); std::vector textures = data.getTextures(); for (const auto& tex : textures) { - urde::SObjectTag texTag = tagFromPath(tex, btok); + urde::SObjectTag texTag = tagFromPath(tex); if (!texTag) Log.report(logvisor::Fatal, _SYS_STR("Unable to resolve %s"), tex.getRelativePath().data()); listOut.push_back(texTag); @@ -1270,14 +1267,13 @@ struct SpecMP1 : SpecBase { }; hecl::Database::DataSpecEntry SpecEntMP1 = { - _SYS_STR("MP1"sv), _SYS_STR("Data specification for original Metroid Prime engine"sv), _SYS_STR(".pak"sv), 2, + _SYS_STR("MP1"sv), _SYS_STR("Data specification for original Metroid Prime engine"sv), _SYS_STR(".pak"sv), [](hecl::Database::Project& project, hecl::Database::DataSpecTool) -> std::unique_ptr { return std::make_unique(&SpecEntMP1, project, false); }}; hecl::Database::DataSpecEntry SpecEntMP1PC = { _SYS_STR("MP1-PC"sv), _SYS_STR("Data specification for PC-optimized Metroid Prime engine"sv), _SYS_STR(".upak"sv), - 2, [](hecl::Database::Project& project, hecl::Database::DataSpecTool tool) -> std::unique_ptr { if (tool != hecl::Database::DataSpecTool::Extract) @@ -1286,5 +1282,5 @@ hecl::Database::DataSpecEntry SpecEntMP1PC = { }}; hecl::Database::DataSpecEntry SpecEntMP1ORIG = { - _SYS_STR("MP1-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime resources"sv), {}, 2, {}}; + _SYS_STR("MP1-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime resources"sv), {}, {}}; } // namespace DataSpec diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index 08bfc4b77..50628b4e8 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -359,7 +359,7 @@ struct SpecMP2 : SpecBase { }); } - urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { return {}; } + urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path) const { return {}; } void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, hecl::blender::Token& btok, FCookProgress progress) {} @@ -430,14 +430,13 @@ struct SpecMP2 : SpecBase { }; hecl::Database::DataSpecEntry SpecEntMP2( - _SYS_STR("MP2"sv), _SYS_STR("Data specification for original Metroid Prime 2 engine"sv), _SYS_STR(".pak"sv), 2, + _SYS_STR("MP2"sv), _SYS_STR("Data specification for original Metroid Prime 2 engine"sv), _SYS_STR(".pak"sv), [](hecl::Database::Project& project, hecl::Database::DataSpecTool) -> std::unique_ptr { return std::make_unique(&SpecEntMP2, project, false); }); hecl::Database::DataSpecEntry SpecEntMP2PC = { _SYS_STR("MP2-PC"sv), _SYS_STR("Data specification for PC-optimized Metroid Prime 2 engine"sv), _SYS_STR(".upak"sv), - 2, [](hecl::Database::Project& project, hecl::Database::DataSpecTool tool) -> std::unique_ptr { if (tool != hecl::Database::DataSpecTool::Extract) @@ -446,6 +445,6 @@ hecl::Database::DataSpecEntry SpecEntMP2PC = { }}; hecl::Database::DataSpecEntry SpecEntMP2ORIG = { - _SYS_STR("MP2-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime 2 resources"sv), {}, 2, {}}; + _SYS_STR("MP2-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime 2 resources"sv), {}, {}}; } // namespace DataSpec diff --git a/DataSpec/SpecMP3.cpp b/DataSpec/SpecMP3.cpp index 61ab13132..6ccc792af 100644 --- a/DataSpec/SpecMP3.cpp +++ b/DataSpec/SpecMP3.cpp @@ -517,7 +517,7 @@ struct SpecMP3 : SpecBase { return false; } - urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { return {}; } + urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path) const { return {}; } void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, hecl::blender::Token& btok, FCookProgress progress) {} @@ -577,14 +577,13 @@ struct SpecMP3 : SpecBase { }; hecl::Database::DataSpecEntry SpecEntMP3( - _SYS_STR("MP3"sv), _SYS_STR("Data specification for original Metroid Prime 3 engine"sv), _SYS_STR(".pak"sv), 2, + _SYS_STR("MP3"sv), _SYS_STR("Data specification for original Metroid Prime 3 engine"sv), _SYS_STR(".pak"sv), [](hecl::Database::Project& project, hecl::Database::DataSpecTool) -> std::unique_ptr { return std::make_unique(&SpecEntMP3, project, false); }); hecl::Database::DataSpecEntry SpecEntMP3PC = { _SYS_STR("MP3-PC"sv), _SYS_STR("Data specification for PC-optimized Metroid Prime 3 engine"sv), _SYS_STR(".upak"sv), - 2, [](hecl::Database::Project& project, hecl::Database::DataSpecTool tool) -> std::unique_ptr { if (tool != hecl::Database::DataSpecTool::Extract) @@ -593,6 +592,6 @@ hecl::Database::DataSpecEntry SpecEntMP3PC = { }}; hecl::Database::DataSpecEntry SpecEntMP3ORIG = { - _SYS_STR("MP3-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime 3 resources"sv), {}, 2, {}}; + _SYS_STR("MP3-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime 3 resources"sv), {}, {}}; } // namespace DataSpec diff --git a/Editor/ProjectManager.cpp b/Editor/ProjectManager.cpp index 9b1cdd680..3c12021d4 100644 --- a/Editor/ProjectManager.cpp +++ b/Editor/ProjectManager.cpp @@ -14,7 +14,7 @@ CToken ProjectResourcePool::GetObj(std::string_view name) { hecl::ProjectPath path(*m_parent.project(), name); SObjectTag tag = - static_cast(x18_factory).TagFromPath(path, hecl::blender::SharedBlenderToken); + static_cast(x18_factory).TagFromPath(path); if (tag) return CSimplePool::GetObj(tag); @@ -28,7 +28,7 @@ CToken ProjectResourcePool::GetObj(std::string_view name, const CVParamTransfer& hecl::ProjectPath path(*m_parent.project(), name); SObjectTag tag = - static_cast(x18_factory).TagFromPath(path, hecl::blender::SharedBlenderToken); + static_cast(x18_factory).TagFromPath(path); if (tag) return CSimplePool::GetObj(tag, pvxfer); diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index f8bb5635d..acf45819b 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -61,7 +61,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& t m_cookedPath = path.getCookedPath(*m_parent.m_origSpec); if (!m_cookedPath.isFile() || m_cookedPath.getModtime() < path.getModtime()) { /* Last chance type validation */ - urde::SObjectTag verifyTag = m_parent.TagFromPath(path, hecl::blender::SharedBlenderToken); + urde::SObjectTag verifyTag = m_parent.TagFromPath(path); if (verifyTag.type != tag.type) { Log.report(logvisor::Error, _SYS_STR("%s: expected type '%.4s', found '%.4s'"), path.getRelativePath().data(), tag.type.getChars(), verifyTag.type.getChars()); @@ -179,7 +179,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he cooked = path.getCookedPath(*m_origSpec); if (!cooked.isFile() || cooked.getModtime() < path.getModtime()) { /* Last chance type validation */ - urde::SObjectTag verifyTag = TagFromPath(path, hecl::blender::SharedBlenderToken); + urde::SObjectTag verifyTag = TagFromPath(path); if (verifyTag.type != tag.type) { Log.report(logvisor::Error, _SYS_STR("%s: expected type '%.4s', found '%.4s'"), path.getRelativePath().data(), tag.type.getChars(), verifyTag.type.getChars()); diff --git a/Editor/ProjectResourceFactoryBase.hpp b/Editor/ProjectResourceFactoryBase.hpp index 6924fa677..31bbede12 100644 --- a/Editor/ProjectResourceFactoryBase.hpp +++ b/Editor/ProjectResourceFactoryBase.hpp @@ -96,11 +96,11 @@ protected: bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) { return static_cast(*m_cookSpec).waitForTagReady(tag, pathOut); } - SObjectTag TagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { - return static_cast(*m_cookSpec).tagFromPath(path, btok); + SObjectTag TagFromPath(const hecl::ProjectPath& path) const { + return static_cast(*m_cookSpec).tagFromPath(path); } - SObjectTag BuildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { - return static_cast(*m_cookSpec).buildTagFromPath(path, btok); + SObjectTag BuildTagFromPath(const hecl::ProjectPath& path) const { + return static_cast(*m_cookSpec).buildTagFromPath(path); } void GetTagListForFile(const char* pakName, std::vector& out) const { return static_cast(*m_cookSpec).getTagListForFile(pakName, out); @@ -150,7 +150,7 @@ public: bool IsBusy() const { return m_asyncLoadMap.size() != 0; } SObjectTag TagFromPath(hecl::SystemStringView path) const { - return TagFromPath(hecl::ProjectPath(*(hecl::Database::Project*)m_proj, path), hecl::blender::SharedBlenderToken); + return TagFromPath(hecl::ProjectPath(*(hecl::Database::Project*)m_proj, path)); } ~ProjectResourceFactoryBase() { Shutdown(); } diff --git a/Runtime/CMakeLists.txt b/Runtime/CMakeLists.txt index 7b8fe56ce..76f2b92ea 100644 --- a/Runtime/CMakeLists.txt +++ b/Runtime/CMakeLists.txt @@ -5,7 +5,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} macro(runtime_add_list rel_path a_list) unset(tmp_list) foreach(path IN LISTS ${a_list}) - list(APPEND tmp_list "${rel_path}/${path}") + if(IS_ABSOLUTE ${path}) + list(APPEND tmp_list "${path}") + else() + list(APPEND tmp_list "${rel_path}/${path}") + endif() endforeach(path) set(${a_list} "${tmp_list}" PARENT_SCOPE) endmacro(runtime_add_list) @@ -144,3 +148,5 @@ if(MSVC) else() add_runtime_common_library(RuntimeCommon ${RUNTIME_SOURCES_A} ${RUNTIME_SOURCES_B}) endif() + +target_link_libraries(RuntimeCommon CModelShaders) \ No newline at end of file diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index 4caa6e0d9..b94083b53 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -339,7 +339,7 @@ float CPlayerState::CalculateHealth() { return (GetEnergyTankCapacity() * x24_powerups[u32(EItemType::EnergyTanks)].x0_amount) + GetBaseHealthCapacity(); } -void CPlayerState::InitializePowerUp(CPlayerState::EItemType type, u32 capacity) { +void CPlayerState::AddPowerUp(CPlayerState::EItemType type, u32 capacity) { if (type >= EItemType::Max) return; @@ -360,7 +360,7 @@ void CPlayerState::InitializePowerUp(CPlayerState::EItemType type, u32 capacity) void CPlayerState::ReInitalizePowerUp(CPlayerState::EItemType type, u32 capacity) { x24_powerups[u32(type)].x4_capacity = 0; - InitializePowerUp(type, capacity); + AddPowerUp(type, capacity); } void CPlayerState::InitializeScanTimes() { diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index e885000b1..773fa8e76 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -160,7 +160,7 @@ public: static float GetBaseHealthCapacity() { return 99.f; } float CalculateHealth(); void ReInitalizePowerUp(EItemType type, u32 capacity); - void InitializePowerUp(EItemType type, u32 capacity); + void AddPowerUp(EItemType type, u32 capacity); u32 GetLogScans() const { return x180_scanCompletionRate.first; } u32 GetTotalLogScans() const { return x180_scanCompletionRate.second; } void SetScanCompletionRate(const std::pair& p) { x180_scanCompletionRate = p; } diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index 0088ddee1..49ce9bc20 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -2068,7 +2068,7 @@ void CStateManager::InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaI u32 spawnPu = sp->GetPowerup(iType); u32 statePu = x8b8_playerState->GetItemAmount(iType); if (statePu < spawnPu) - x8b8_playerState->InitializePowerUp(iType, spawnPu - statePu); + x8b8_playerState->AddPowerUp(iType, spawnPu - statePu); spawnPu = sp->GetPowerup(iType); statePu = x8b8_playerState->GetItemAmount(iType); diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index b469050ae..9c0d6be11 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -168,7 +168,7 @@ void Buckets::Init() { CBooRenderer::CAreaListItem::CAreaListItem(const std::vector* geom, const CAreaRenderOctTree* octTree, - std::vector>&& textures, + std::unordered_map>&& textures, std::vector&& models, int areaIdx, const SShader* shaderSet) : x0_geometry(geom) , x4_octTree(octTree) @@ -593,6 +593,22 @@ void CBooRenderer::GenerateScanLinesVBO(boo::IGraphicsDataFactory::Context& ctx) m_scanLinesOddVBO = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), sizeof(zeus::CVector3f), verts.size()); } +boo::ObjToken CBooRenderer::GetColorTexture(const zeus::CColor& color) { + auto search = m_colorTextures.find(color); + if (search != m_colorTextures.end()) + return search->second; + u8 pixel[4]; + color.toRGBA8(pixel[0], pixel[1], pixel[2], pixel[3]); + boo::ObjToken tex; + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + tex = ctx.newStaticTexture(1, 1, 1, boo::TextureFormat::RGBA8, + boo::TextureClampMode::Repeat, pixel, 4).get(); + return true; + } BooTrace); + m_colorTextures.insert(std::make_pair(color, tex)); + return tex; +} + void CBooRenderer::LoadThermoPalette() { m_thermoPaletteTex = xc_store.GetObj("TXTR_ThermoPalette"); CTexture* thermoTexObj = m_thermoPaletteTex.GetObj(); @@ -652,8 +668,7 @@ void CBooRenderer::AddWorldSurfaces(CBooModel& model) { zeus::CAABox aabb = surf->GetBounds(); zeus::CVector3f pt = aabb.closestPointAlongVector(xb0_viewPlane.normal()); Buckets::Insert(pt, aabb, EDrawableType::WorldSurface, surf, xb0_viewPlane, - mat.heclIr.m_blendSrc == boo::BlendFactor::SrcAlpha && - mat.heclIr.m_blendDst == boo::BlendFactor::InvSrcAlpha); + mat.blendMode == MaterialSet::Material::BlendMaterial::BlendMode::Alpha); surf = surf->m_next; } } @@ -668,7 +683,7 @@ void CBooRenderer::AddStaticGeometry(const std::vector* g const CAreaRenderOctTree* octTree, int areaIdx, const SShader* shaderSet) { auto search = FindStaticGeometry(geometry); if (search == x1c_areaListItems.end()) { - std::vector> textures; + std::unordered_map> textures; std::vector models; if (geometry->size()) { (*geometry)[0].m_instance->MakeTexturesFromMats(textures, xc_store); diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index c3c1f4bc6..97b85b648 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -58,7 +58,7 @@ class CBooRenderer final : public IRenderer { const std::vector* x0_geometry; const CAreaRenderOctTree* x4_octTree; /* originally auto_ptrs of vectors */ - std::vector> x8_textures; + std::unordered_map> x8_textures; std::vector x10_models; int x18_areaIdx; /* Per-area octree-word major, light bits minor */ @@ -66,8 +66,8 @@ class CBooRenderer final : public IRenderer { const SShader* m_shaderSet; CAreaListItem(const std::vector* geom, const CAreaRenderOctTree* octTree, - std::vector>&& textures, std::vector&& models, int areaIdx, - const SShader* shaderSet); + std::unordered_map>&& textures, std::vector&& models, + int areaIdx, const SShader* shaderSet); ~CAreaListItem(); }; @@ -109,6 +109,7 @@ class CBooRenderer final : public IRenderer { boo::ObjToken m_clearTexture; boo::ObjToken m_blackTexture; boo::ObjToken m_whiteTexture; + std::unordered_map> m_colorTextures; boo::ObjToken x14c_reflectionTex; // boo::ITextureS* x150_mirrorRamp = nullptr; @@ -278,6 +279,8 @@ public: const boo::ObjToken& GetBlackTexture() { return m_blackTexture; } const boo::ObjToken& GetWhiteTexture() { return m_whiteTexture; } + boo::ObjToken GetColorTexture(const zeus::CColor& color); + static void BindMainDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(CGraphics::g_SpareTexture); } void BindReflectionDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(x14c_reflectionTex); } void BindBallShadowIdTarget() { diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index a99243969..c19f80790 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -24,7 +24,6 @@ set(GRAPHICS_SOURCES Shaders/CColoredQuadFilter.hpp Shaders/CColoredQuadFilter.cpp Shaders/CColoredStripShader.hpp Shaders/CColoredStripShader.cpp Shaders/CModelShaders.hpp Shaders/CModelShaders.cpp - Shaders/CModelShadersGLSL.cpp Shaders/CModelShadersHLSL.cpp Shaders/CModelShadersMetal.cpp Shaders/CThermalColdFilter.hpp Shaders/CThermalColdFilter.cpp Shaders/CThermalHotFilter.hpp Shaders/CThermalHotFilter.cpp Shaders/CSpaceWarpFilter.hpp Shaders/CSpaceWarpFilter.cpp diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 2ca00c39f..4bf18807a 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -75,7 +75,6 @@ struct CBooSurface { }; using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet; -using UVAnimation = DataSpec::DNAMP1::MaterialSet::Material::UVAnimation; struct GeometryUniformLayout { boo::ObjToken m_sharedBuffer[2]; @@ -96,7 +95,7 @@ struct GeometryUniformLayout { }; struct SShader { - std::vector> x0_textures; + std::unordered_map> x0_textures; std::unordered_map m_shaders; MaterialSet m_matSet; rstl::optional m_geomLayout; @@ -134,7 +133,7 @@ private: const GeometryUniformLayout* m_geomLayout; int m_matSetIdx = -1; const std::unordered_map* m_pipelines; - std::vector> x1c_textures; + std::unordered_map> x1c_textures; zeus::CAABox x20_aabb; CBooSurface* x38_firstUnsortedSurface = nullptr; CBooSurface* x3c_firstSortedSurface = nullptr; @@ -144,7 +143,7 @@ private: u32 x44_areaInstanceIdx = -1; struct UVAnimationBuffer { - static void ProcessAnimation(u8*& bufOut, const UVAnimation& anim); + static void ProcessAnimation(u8*& bufOut, const MaterialSet::Material::PASS& anim); static void PadOutBuffer(u8*& bufStart, u8*& bufOut); static void Update(u8*& bufOut, const MaterialSet* matSet, const CModelFlags& flags, const CBooModel* parent); }; @@ -166,8 +165,6 @@ private: boo::ObjToken m_staticVbo; boo::ObjToken m_staticIbo; - boo::ObjToken m_txtrOverrides[8]; - boo::ObjToken m_lastDrawnShadowMap; boo::ObjToken m_lastDrawnOneTexture; @@ -192,11 +189,12 @@ public: ~CBooModel(); CBooModel(TToken& token, CModel* parent, std::vector* surfaces, SShader& shader, const boo::ObjToken& vbo, const boo::ObjToken& ibo, - const zeus::CAABox& aabb, u8 renderMask, int numInsts, const boo::ObjToken txtrOverrides[8]); + const zeus::CAABox& aabb, u8 renderMask, int numInsts); - static void MakeTexturesFromMats(const MaterialSet& matSet, std::vector>& toksOut, + static void MakeTexturesFromMats(const MaterialSet& matSet, + std::unordered_map>& toksOut, IObjectStore& store); - void MakeTexturesFromMats(std::vector>& toksOut, IObjectStore& store); + void MakeTexturesFromMats(std::unordered_map>& toksOut, IObjectStore& store); bool IsOpaque() const { return x3c_firstSortedSurface == nullptr; } void ActivateLights(const std::vector& lights); @@ -284,9 +282,7 @@ public: const zeus::CAABox& GetAABB() const { return m_aabb; } CBooModel& GetInstance() { return *x28_modelInst; } const CBooModel& GetInstance() const { return *x28_modelInst; } - std::unique_ptr MakeNewInstance(int shaderIdx, int subInsts, - const boo::ObjToken txtrOverrides[8] = nullptr, - bool lockParent = true); + std::unique_ptr MakeNewInstance(int shaderIdx, int subInsts, bool lockParent = true); void UpdateLastFrame() const { const_cast(*this).x38_lastFrame = CGraphics::GetFrameCounter(); } size_t GetPoolVertexOffset(size_t idx) const; diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index 7223f84c3..ab3b75d70 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -141,8 +141,7 @@ CBooModel::~CBooModel() { CBooModel::CBooModel(TToken& token, CModel* parent, std::vector* surfaces, SShader& shader, const boo::ObjToken& vbo, const boo::ObjToken& ibo, - const zeus::CAABox& aabb, u8 renderMask, int numInsts, - const boo::ObjToken txtrOverrides[8]) + const zeus::CAABox& aabb, u8 renderMask, int numInsts) : m_modelTok(token) , m_model(parent) , x0_surfaces(surfaces) @@ -157,10 +156,6 @@ CBooModel::CBooModel(TToken& token, CModel* parent, std::vectorsize()); - boo::ObjToken mbShadowTexs[8] = { - g_Renderer->m_ballShadowId.get(), g_Renderer->x220_sphereRamp.get(), g_Renderer->m_ballFade.get(), - g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get()}; size_t thisOffs[4]; size_t thisSizes[4]; @@ -306,20 +297,23 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { for (const CBooSurface& surf : *x0_surfaces) { const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); - boo::ObjToken texs[8] = {g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get()}; - u32 texCount = 0; - for (atUint32 idx : mat.textureIdxs) { - if (boo::ObjToken overtex = m_txtrOverrides[texCount]) { - texs[texCount++] = overtex; - } else if (g_DummyTextures) { - texs[texCount++] = g_Renderer->x220_sphereRamp.get(); - } else { - TCachedToken& tex = x1c_textures[idx]; - if (boo::ObjToken btex = tex.GetObj()->GetBooTexture()) - texs[texCount++] = btex; + boo::ObjToken texs[12] = {g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), + g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), + g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), + g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get()}; + if (!g_DummyTextures) { + for (const auto& ch : mat.chunks) { + if (auto pass = ch.get_if()) { + auto search = x1c_textures.find(pass->texId.toUint32()); + boo::ObjToken btex; + if (search != x1c_textures.cend() && (btex = search->second.GetObj()->GetBooTexture())) + texs[MaterialSet::Material::TexMapIdx(pass->type)] = btex; + } else if (auto pass = ch.get_if()) { + boo::ObjToken btex = g_Renderer->GetColorTexture(zeus::CColor(pass->color)); + texs[MaterialSet::Material::TexMapIdx(pass->type)] = btex; + } } } @@ -340,9 +334,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { bool useReflection = mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye(); if (useReflection) { if (g_Renderer->x14c_reflectionTex) - texs[texCount] = g_Renderer->x14c_reflectionTex.get(); - else - texs[texCount] = g_Renderer->x220_sphereRamp.get(); + texs[11] = g_Renderer->x14c_reflectionTex.get(); thisOffs[3] = curReflect; curReflect += 256; } else { @@ -358,31 +350,25 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { int idx = 0; for (const auto& pipeline : *pipelines) { - boo::ObjToken* ltexs; if (idx == EExtendedShader::Thermal) { - texs[7] = g_Renderer->x220_sphereRamp.get(); - ltexs = texs; + texs[8] = g_Renderer->x220_sphereRamp.get(); } else if (idx == EExtendedShader::MorphBallShadow) { - ltexs = mbShadowTexs; + texs[8] = g_Renderer->m_ballShadowId.get(); + texs[9] = g_Renderer->x220_sphereRamp.get(); + texs[10] = g_Renderer->m_ballFade.get(); } else if (idx == EExtendedShader::WorldShadow) { if (g_shadowMap) - texs[7] = g_shadowMap; + texs[8] = g_shadowMap; else - texs[7] = g_Renderer->x220_sphereRamp.get(); - ltexs = texs; + texs[8] = g_Renderer->x220_sphereRamp.get(); } else if (idx == EExtendedShader::Disintegrate) { if (g_disintegrateTexture) - texs[7] = g_disintegrateTexture; + texs[8] = g_disintegrateTexture; else - texs[7] = g_Renderer->x220_sphereRamp.get(); - ltexs = texs; - } else if (useReflection) { - ltexs = texs; - } else { - ltexs = texs; + texs[8] = g_Renderer->x220_sphereRamp.get(); } extendeds.push_back(ctx.newShaderDataBinding(pipeline, newInst.GetBooVBO(*this, ctx), nullptr, - m_staticIbo.get(), 4, bufs, stages, thisOffs, thisSizes, 8, ltexs, + m_staticIbo.get(), 4, bufs, stages, thisOffs, thisSizes, 12, texs, nullptr, nullptr)); ++idx; } @@ -393,14 +379,20 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { return &newInst; } -void CBooModel::MakeTexturesFromMats(const MaterialSet& matSet, std::vector>& toksOut, +void CBooModel::MakeTexturesFromMats(const MaterialSet& matSet, + std::unordered_map>& toksOut, IObjectStore& store) { - toksOut.reserve(matSet.head.textureIDs.size()); - for (const DataSpec::UniqueID32& id : matSet.head.textureIDs) - toksOut.emplace_back(store.GetObj({SBIG('TXTR'), id.toUint32()})); + for (const auto& mat : matSet.materials) { + for (const auto& chunk : mat.chunks) { + if (auto pass = chunk.get_if()) { + toksOut.emplace(std::make_pair(pass->texId.toUint32(), store.GetObj({SBIG('TXTR'), pass->texId.toUint32()}))); + } + } + } } -void CBooModel::MakeTexturesFromMats(std::vector>& toksOut, IObjectStore& store) { +void CBooModel::MakeTexturesFromMats(std::unordered_map>& toksOut, + IObjectStore& store) { MakeTexturesFromMats(*x4_matSet, toksOut, store); } @@ -445,9 +437,9 @@ void CBooModel::RemapMaterialData(SShader& shader, bool CBooModel::TryLockTextures() const { if (!x40_24_texturesLoaded) { bool allLoad = true; - for (TCachedToken& tex : const_cast>&>(x1c_textures)) { - tex.Lock(); - if (!tex.IsLoaded()) + for (auto& tex : const_cast>&>(x1c_textures)) { + tex.second.Lock(); + if (!tex.second.IsLoaded()) allLoad = false; } @@ -459,15 +451,15 @@ bool CBooModel::TryLockTextures() const { void CBooModel::UnlockTextures() const { const_cast(this)->m_instances.clear(); - for (TCachedToken& tex : const_cast>&>(x1c_textures)) - tex.Unlock(); + for (auto& tex : const_cast>&>(x1c_textures)) + tex.second.Unlock(); const_cast(this)->x40_24_texturesLoaded = false; } void CBooModel::SyncLoadTextures() const { if (!x40_24_texturesLoaded) { - for (TCachedToken& tex : const_cast>&>(x1c_textures)) - tex.GetObj(); + for (auto& tex : const_cast>&>(x1c_textures)) + tex.second.GetObj(); const_cast(this)->x40_24_texturesLoaded = true; } } @@ -534,7 +526,7 @@ static EExtendedShader ResolveExtendedShader(const MaterialSet::Material& data, return EExtendedShader::LightingAlphaWrite; else if (g_Renderer->IsThermalVisorActive()) return EExtendedShader::ThermalCold; - if (data.heclIr.m_blendSrc == boo::BlendFactor::One && data.heclIr.m_blendDst == boo::BlendFactor::Zero) { + if (data.blendMode == MaterialSet::Material::BlendMaterial::BlendMode::Opaque) { /* Override shader if originally opaque (typical for FRME models) */ if (flags.x0_blendMode > 6) { if (flags.m_depthGreater) @@ -555,19 +547,19 @@ static EExtendedShader ResolveExtendedShader(const MaterialSet::Material& data, } } else if (flags.m_noCull && noZWrite) { /* Substitute no-cull,no-zwrite pipeline if available */ - if (data.heclIr.m_blendDst == boo::BlendFactor::One) + if (data.blendMode == MaterialSet::Material::BlendMaterial::BlendMode::Additive) extended = EExtendedShader::ForcedAdditiveNoCullNoZWrite; else extended = EExtendedShader::ForcedAlphaNoCullNoZWrite; } else if (flags.m_noCull) { /* Substitute no-cull pipeline if available */ - if (data.heclIr.m_blendDst == boo::BlendFactor::One) + if (data.blendMode == MaterialSet::Material::BlendMaterial::BlendMode::Additive) extended = EExtendedShader::ForcedAdditiveNoCull; else extended = EExtendedShader::ForcedAlphaNoCull; } else if (noZWrite) { /* Substitute no-zwrite pipeline if available */ - if (data.heclIr.m_blendDst == boo::BlendFactor::One) + if (data.blendMode == MaterialSet::Material::BlendMaterial::BlendMode::Additive) extended = EExtendedShader::ForcedAdditiveNoZWrite; else extended = EExtendedShader::ForcedAlphaNoZWrite; @@ -619,21 +611,22 @@ void CBooModel::WarmupDrawSurface(const CBooSurface& surf) const { return; const ModelInstance& inst = m_instances[m_uniUpdateCount - 1]; - // Only warmup normal lighting and thermal visor - for (int i = 1; i <= 2; ++i) { - auto& binding = inst.m_shaderDataBindings[surf.selfIdx][i]; + for (auto& binding : inst.m_shaderDataBindings[surf.selfIdx]) { CGraphics::SetShaderDataBinding(binding); CGraphics::DrawArrayIndexed(surf.m_data.idxStart, std::min(u32(3), surf.m_data.idxCount)); } } -void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimation& anim) { +void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const MaterialSet::Material::PASS& anim) { + using UVAnimType = MaterialSet::Material::BlendMaterial::UVAnimType; + if (anim.uvAnimType == UVAnimType::Invalid) + return; zeus::CMatrix4f& texMtxOut = reinterpret_cast(*bufOut); zeus::CMatrix4f& postMtxOut = reinterpret_cast(*(bufOut + sizeof(zeus::CMatrix4f))); texMtxOut = zeus::CMatrix4f(); postMtxOut = zeus::CMatrix4f(); - switch (anim.mode) { - case UVAnimation::Mode::MvInvNoTranslation: { + switch (anim.uvAnimType) { + case UVAnimType::MvInvNoTranslation: { texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); texMtxOut[3].w() = 1.f; postMtxOut[0].x() = 0.5f; @@ -642,7 +635,7 @@ void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimati postMtxOut[3].y() = 0.5f; break; } - case UVAnimation::Mode::MvInv: { + case UVAnimType::MvInv: { texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); texMtxOut[3] = CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix.origin; texMtxOut[3].w() = 1.f; @@ -652,13 +645,13 @@ void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimati postMtxOut[3].y() = 0.5f; break; } - case UVAnimation::Mode::Scroll: { - texMtxOut[3].x() = CGraphics::GetSecondsMod900() * anim.vals[2] + anim.vals[0]; - texMtxOut[3].y() = CGraphics::GetSecondsMod900() * anim.vals[3] + anim.vals[1]; + case UVAnimType::Scroll: { + texMtxOut[3].x() = CGraphics::GetSecondsMod900() * anim.uvAnimParms[2] + anim.uvAnimParms[0]; + texMtxOut[3].y() = CGraphics::GetSecondsMod900() * anim.uvAnimParms[3] + anim.uvAnimParms[1]; break; } - case UVAnimation::Mode::Rotation: { - float angle = CGraphics::GetSecondsMod900() * anim.vals[1] + anim.vals[0]; + case UVAnimType::Rotation: { + float angle = CGraphics::GetSecondsMod900() * anim.uvAnimParms[1] + anim.uvAnimParms[0]; float acos = std::cos(angle); float asin = std::sin(angle); texMtxOut[0].x() = acos; @@ -669,17 +662,17 @@ void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimati texMtxOut[3].y() = (1.0f - (asin + acos)) * 0.5f; break; } - case UVAnimation::Mode::HStrip: { - float value = anim.vals[0] * anim.vals[2] * (anim.vals[3] + CGraphics::GetSecondsMod900()); - texMtxOut[3].x() = std::trunc(anim.vals[1] * fmod(value, 1.0f)) * anim.vals[2]; + case UVAnimType::HStrip: { + float value = anim.uvAnimParms[0] * anim.uvAnimParms[2] * (anim.uvAnimParms[3] + CGraphics::GetSecondsMod900()); + texMtxOut[3].x() = std::trunc(anim.uvAnimParms[1] * fmod(value, 1.0f)) * anim.uvAnimParms[2]; break; } - case UVAnimation::Mode::VStrip: { - float value = anim.vals[0] * anim.vals[2] * (anim.vals[3] + CGraphics::GetSecondsMod900()); - texMtxOut[3].y() = std::trunc(anim.vals[1] * fmod(value, 1.0f)) * anim.vals[2]; + case UVAnimType::VStrip: { + float value = anim.uvAnimParms[0] * anim.uvAnimParms[2] * (anim.uvAnimParms[3] + CGraphics::GetSecondsMod900()); + texMtxOut[3].y() = std::trunc(anim.uvAnimParms[1] * fmod(value, 1.0f)) * anim.uvAnimParms[2]; break; } - case UVAnimation::Mode::Model: { + case UVAnimType::Model: { texMtxOut = CGraphics::g_GXModelMatrix.toMatrix4f(); texMtxOut[3] = zeus::CVector4f(0.f, 0.f, 0.f, 1.f); postMtxOut[0].x() = 0.5f; @@ -689,16 +682,16 @@ void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimati postMtxOut[3].y() = CGraphics::g_GXModelMatrix.origin.y() * 0.05f; break; } - case UVAnimation::Mode::CylinderEnvironment: { + case UVAnimType::CylinderEnvironment: { texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); const zeus::CVector3f& viewOrigin = CGraphics::g_ViewMatrix.origin; - float xy = (viewOrigin.x() + viewOrigin.y()) * 0.025f * anim.vals[1]; + float xy = (viewOrigin.x() + viewOrigin.y()) * 0.025f * anim.uvAnimParms[1]; xy = (xy - std::trunc(xy)); - float z = (viewOrigin.z()) * 0.05f * anim.vals[1]; + float z = (viewOrigin.z()) * 0.05f * anim.uvAnimParms[1]; z = (z - std::trunc(z)); - float halfA = anim.vals[0] * 0.5f; + float halfA = anim.uvAnimParms[0] * 0.5f; postMtxOut = zeus::CTransform(zeus::CMatrix3f(halfA, 0.0, 0.0, 0.0, 0.0, halfA, 0.0, 0.0, 0.0), zeus::CVector3f(xy, z, 1.0)) @@ -808,8 +801,11 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet mtxs[7][1] = (*specialMtxOut)[1]; } u8* bufOrig = bufOut; - for (const UVAnimation& anim : mat.uvAnims) - ProcessAnimation(bufOut, anim); + for (const auto& chunk : mat.chunks) { + if (auto pass = chunk.get_if()) { + ProcessAnimation(bufOut, *pass); + } + } bufOut = bufOrig + sizeof(zeus::CMatrix4f) * 2 * 8; PadOutBuffer(start, bufOut); } @@ -898,7 +894,7 @@ void GeometryUniformLayout::Update(const CModelFlags& flags, const CSkinRules* c boo::ObjToken CBooModel::UpdateUniformData(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose, int sharedLayoutBuf) const { - if (!TryLockTextures()) + if (!g_DummyTextures && !TryLockTextures()) return {}; /* Invalidate instances if new shadow being drawn */ @@ -1046,13 +1042,11 @@ static const u8* MemoryFromPartData(const u8*& dataCur, const u32*& secSizeCur) return ret; } -std::unique_ptr CModel::MakeNewInstance(int shaderIdx, int subInsts, - const boo::ObjToken txtrOverrides[8], - bool lockParent) { +std::unique_ptr CModel::MakeNewInstance(int shaderIdx, int subInsts, bool lockParent) { if (shaderIdx >= x18_matSets.size()) shaderIdx = 0; auto ret = std::make_unique(m_selfToken, this, &x8_surfaces, x18_matSets[shaderIdx], m_staticVbo, m_ibo, - m_aabb, (m_flags & 0x2) != 0, subInsts, txtrOverrides); + m_aabb, (m_flags & 0x2) != 0, subInsts); if (lockParent) ret->LockParent(); return ret; @@ -1066,9 +1060,9 @@ CModelShaders::ShaderPipelines SShader::BuildShader(const hecl::HMDLMeta& meta, reflectionType = hecl::Backend::ReflectionType::Simple; else reflectionType = hecl::Backend::ReflectionType::None; - hecl::Backend::ShaderTag tag(mat.heclIr, meta.colorCount, meta.uvCount, meta.weightCount, meta.weightCount * 4, + hecl::Backend::ShaderTag tag(mat.hash, meta.colorCount, meta.uvCount, meta.weightCount, meta.weightCount * 4, boo::Primitive(meta.topology), reflectionType, true, true, true, mat.flags.alphaTest()); - return CModelShaders::BuildExtendedShader(tag, mat.heclIr); + return CModelShaders::BuildExtendedShader(tag, mat); } void SShader::BuildShaders(const hecl::HMDLMeta& meta, @@ -1156,12 +1150,12 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor const float* aabbPtr = reinterpret_cast(data.get() + 0xc); m_aabb = zeus::CAABox(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]), hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5])); - x28_modelInst = MakeNewInstance(0, 1, nullptr, false); + x28_modelInst = MakeNewInstance(0, 1, false); } void SShader::UnlockTextures() { - for (TCachedToken& tex : x0_textures) - tex.Unlock(); + for (auto& tex : x0_textures) + tex.second.Unlock(); } void CBooModel::VerifyCurrentShader(int shaderIdx) { diff --git a/Runtime/Graphics/Shaders/CModelShaders.cpp b/Runtime/Graphics/Shaders/CModelShaders.cpp index 969f3a126..fd6dbe47f 100644 --- a/Runtime/Graphics/Shaders/CModelShaders.cpp +++ b/Runtime/Graphics/Shaders/CModelShaders.cpp @@ -54,142 +54,138 @@ void CModelShaders::LightingUniform::ActivateLights(const std::vector& l } } -static const hecl::Backend::TextureInfo ThermalTextures[] = {{hecl::Backend::TexGenSrc::Normal, 7, 0, 7, true}}; +using TexCoordSource = hecl::Backend::TexCoordSource; + +static const hecl::Backend::TextureInfo ThermalTextures[] = {{TexCoordSource::Normal, 7, true}}; static const hecl::Backend::TextureInfo BallFadeTextures[] = { - {hecl::Backend::TexGenSrc::Position, 0, 0, 0, false}, // ID tex - {hecl::Backend::TexGenSrc::Position, 1, 0, 0, false}, // Sphere ramp - {hecl::Backend::TexGenSrc::Position, 2, 0, 1, false} // TXTR_BallFade + {TexCoordSource::Position, 0, false}, // ID tex + {TexCoordSource::Position, 0, false}, // Sphere ramp + {TexCoordSource::Position, 1, false} // TXTR_BallFade }; static const hecl::Backend::TextureInfo WorldShadowTextures[] = { - {hecl::Backend::TexGenSrc::Position, 7, 0, 7, false} // Shadow tex + {TexCoordSource::Position, 7, false} // Shadow tex }; static const hecl::Backend::TextureInfo DisintegrateTextures[] = { - {hecl::Backend::TexGenSrc::Position, 7, 0, 0, false}, // Ashy tex - {hecl::Backend::TexGenSrc::Position, 7, 0, 1, false} // Ashy tex + {TexCoordSource::Position, 0, false}, // Ashy tex + {TexCoordSource::Position, 1, false} // Ashy tex }; -static const char* BlockNames[] = {"LightingUniform"}; -static const char* ThermalBlockNames[] = {"ThermalUniform"}; -static const char* SolidBlockNames[] = {"SolidUniform"}; -static const char* MBShadowBlockNames[] = {"MBShadowUniform"}; -static const char* DisintegrateBlockNames[] = {"DisintegrateUniform"}; - static hecl::Backend::ExtensionSlot g_ExtensionSlots[] = { /* Default solid shading */ {}, /* Normal lit shading */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, + {0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true}, /* Thermal Visor shading */ - {1, ThermalBlockNames, 1, ThermalTextures, hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::One, + {1, ThermalTextures, hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, false, true}, /* Forced alpha shading */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true}, /* Forced additive shading */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true}, /* Solid color */ - {1, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::Zero, + {0, nullptr, hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::Zero, hecl::Backend::ZTest::LEqual, hecl::Backend::CullMode::Backface, false, false, false}, /* Solid color additive */ - {1, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::LEqual, hecl::Backend::CullMode::Backface, true, false, true}, /* Alpha-only Solid color frontface cull, LEqual */ - {1, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::LEqual, hecl::Backend::CullMode::Frontface, false, true, false}, /* Alpha-only Solid color frontface cull, Always, No Z-write */ - {1, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::None, hecl::Backend::CullMode::Frontface, true, true, false}, /* Alpha-only Solid color backface cull, LEqual */ - {1, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::LEqual, hecl::Backend::CullMode::Backface, false, true, false}, /* Alpha-only Solid color backface cull, Greater, No Z-write */ - {1, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Greater, hecl::Backend::CullMode::Backface, true, true, false}, /* MorphBall shadow shading */ - {1, MBShadowBlockNames, 3, BallFadeTextures, hecl::Backend::BlendFactor::SrcAlpha, + {3, BallFadeTextures, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::ZTest::Equal, hecl::Backend::CullMode::Backface, false, false, true, false, true}, /* World shadow shading (modified lighting) */ - {1, BlockNames, 1, WorldShadowTextures, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, + {1, WorldShadowTextures, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true}, /* Forced alpha shading without culling */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::None, false, false, true}, /* Forced additive shading without culling */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::None, false, false, true}, /* Forced alpha shading without Z-write */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Original, true, false, true}, /* Forced additive shading without Z-write */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Original, true, false, true}, /* Forced alpha shading without culling or Z-write */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::None, true, false, true}, /* Forced additive shading without culling or Z-write */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::None, true, false, true}, /* Depth GEqual no Z-write */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::ZTest::GEqual, hecl::Backend::CullMode::Backface, true, false, true}, /* Disintegration */ - {1, DisintegrateBlockNames, 2, DisintegrateTextures, hecl::Backend::BlendFactor::SrcAlpha, + {2, DisintegrateTextures, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::ZTest::LEqual, hecl::Backend::CullMode::Original, false, false, true, false, false, true}, /* Forced additive shading without culling or Z-write and greater depth test */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, + {0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Greater, hecl::Backend::CullMode::None, true, false, true}, /* Thermal cold shading */ - {0, nullptr, 0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, + {0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Original, false, false, true, false, false, false, true}, /* Normal lit shading with alpha */ - {1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, + {0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original, hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface}}; -extern const hecl::Backend::Function ExtensionLightingFuncsGLSL[]; -extern const hecl::Backend::Function ExtensionPostFuncsGLSL[]; -extern const hecl::Backend::Function ExtensionLightingFuncsHLSL[]; -extern const hecl::Backend::Function ExtensionPostFuncsHLSL[]; -extern const hecl::Backend::Function ExtensionLightingFuncsMetal[]; -extern const hecl::Backend::Function ExtensionPostFuncsMetal[]; +const char* ShaderMacros[] = { + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_THERMAL_HOT", + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_SOLID", + "URDE_SOLID", + "URDE_SOLID", + "URDE_SOLID", + "URDE_SOLID", + "URDE_SOLID", + "URDE_MB_SHADOW", + "URDE_LIGHTING_SHADOW", + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_LIGHTING", + "URDE_DISINTEGRATE", + "URDE_LIGHTING", + "URDE_THERMAL_COLD", + "URDE_LIGHTING", +}; void CModelShaders::Initialize() { - const hecl::Backend::Function* lightingFuncs; - const hecl::Backend::Function* postFuncs; - switch (CGraphics::g_BooPlatform) { - case boo::IGraphicsDataFactory::Platform::OpenGL: - case boo::IGraphicsDataFactory::Platform::Vulkan: - case boo::IGraphicsDataFactory::Platform::NX: - default: - lightingFuncs = ExtensionLightingFuncsGLSL; - postFuncs = ExtensionPostFuncsGLSL; - break; - case boo::IGraphicsDataFactory::Platform::D3D11: - lightingFuncs = ExtensionLightingFuncsHLSL; - postFuncs = ExtensionPostFuncsHLSL; - break; - case boo::IGraphicsDataFactory::Platform::Metal: - lightingFuncs = ExtensionLightingFuncsMetal; - postFuncs = ExtensionPostFuncsMetal; - break; - } - for (auto& ext : g_ExtensionSlots) { - ext.lighting = *lightingFuncs++; - ext.post = *postFuncs++; - } + const char** macro = ShaderMacros; + for (auto& ext : g_ExtensionSlots) + ext.shaderMacro = *macro++; } void CModelShaders::Shutdown() { g_ShaderPipelines.clear(); } CModelShaders::ShaderPipelines CModelShaders::BuildExtendedShader(const hecl::Backend::ShaderTag& tag, - const hecl::Frontend::IR& ir) { + const Material& material) { auto search = g_ShaderPipelines.find(tag.val64()); if (search != g_ShaderPipelines.cend()) return search->second; @@ -199,9 +195,10 @@ CModelShaders::ShaderPipelines CModelShaders::BuildExtendedShader(const hecl::Ba CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { size_t idx = 0; for (const auto& ext : g_ExtensionSlots) - (*newPipelines)[idx++] = hecl::conv->convert(ctx, hecl::HECLIR(ir, tag, ext)); + (*newPipelines)[idx++] = hecl::conv->convert(ctx, Shader_CModelShaders(SModelShadersInfo(material, tag, ext))); return true; } BooTrace); return newPipelines; } + } // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShaders.hpp b/Runtime/Graphics/Shaders/CModelShaders.hpp index 8d35ec50e..035e23a0f 100644 --- a/Runtime/Graphics/Shaders/CModelShaders.hpp +++ b/Runtime/Graphics/Shaders/CModelShaders.hpp @@ -1,11 +1,12 @@ #pragma once #include "hecl/Runtime.hpp" -#include "hecl/Backend/Backend.hpp" +#include "hecl/Backend.hpp" #include "optional.hpp" #include "zeus/CVector3f.hpp" #include "zeus/CColor.hpp" #include "Graphics/CGraphics.hpp" +#include "DataSpec/DNAMP1/CMDLMaterials.hpp" #include #define URDE_MAX_LIGHTS 8 @@ -88,7 +89,8 @@ public: using ShaderPipelinesData = std::array, EExtendedShader::MAX>; using ShaderPipelines = std::shared_ptr; - static ShaderPipelines BuildExtendedShader(const hecl::Backend::ShaderTag& tag, const hecl::Frontend::IR& ir); + using Material = DataSpec::DNAMP1::HMDLMaterialSet::Material; + static ShaderPipelines BuildExtendedShader(const hecl::Backend::ShaderTag& tag, const Material& material); private: static std::unordered_map g_ShaderPipelines; diff --git a/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp b/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp deleted file mode 100644 index f3dca84ca..000000000 --- a/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include "CModelShaders.hpp" -#include "hecl/Backend/GLSL.hpp" - -namespace urde { -using namespace std::literals; - -extern const hecl::Backend::Function ExtensionLightingFuncsGLSL[]; -extern const hecl::Backend::Function ExtensionPostFuncsGLSL[]; - -#define FOG_STRUCT_GLSL \ - "struct Fog\n" \ - "{\n" \ - " vec4 color;\n" \ - " float A;\n" \ - " float B;\n" \ - " float C;\n" \ - " int mode;\n" \ - "};\n" - -#define FOG_ALGORITHM_GLSL \ - " float fogZ;\n" \ - " float fogF = clamp((fog.A / (fog.B - gl_FragCoord.z)) - fog.C, 0.0, 1.0);\n" \ - " switch (fog.mode)\n" \ - " {\n" \ - " case 2:\n" \ - " fogZ = fogF;\n" \ - " break;\n" \ - " case 4:\n" \ - " fogZ = 1.0 - exp2(-8.0 * fogF);\n" \ - " break;\n" \ - " case 5:\n" \ - " fogZ = 1.0 - exp2(-8.0 * fogF * fogF);\n" \ - " break;\n" \ - " case 6:\n" \ - " fogZ = exp2(-8.0 * (1.0 - fogF));\n" \ - " break;\n" \ - " case 7:\n" \ - " fogF = 1.0 - fogF;\n" \ - " fogZ = exp2(-8.0 * fogF * fogF);\n" \ - " break;\n" \ - " default:\n" \ - " fogZ = 0.0;\n" \ - " break;\n" \ - " }\n" \ - "#ifdef BLEND_DST_ONE\n" \ - " return vec4(mix(colorIn, vec4(0.0), clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a);\n" \ - "#else\n" \ - " return vec4(mix(colorIn, fog.color, clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a);\n" \ - "#endif\n" - -static std::string_view LightingGLSL = -"struct Light\n" -"{\n" -" vec4 pos;\n" -" vec4 dir;\n" -" vec4 color;\n" -" vec4 linAtt;\n" -" vec4 angAtt;\n" -"};\n" -FOG_STRUCT_GLSL -"\n" -"UBINDING2 uniform LightingUniform\n" -"{\n" -" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n" -" vec4 ambient;\n" -" vec4 colorReg0;\n" -" vec4 colorReg1;\n" -" vec4 colorReg2;\n" -" vec4 mulColor;\n" -" vec4 addColor;\n" -" Fog fog;\n" -"};\n" -"\n" -"vec4 LightingFunc(vec3 mvPosIn, vec3 mvNormIn)\n" -"{\n" -" vec4 ret = ambient;\n" -" \n" -" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n" -" {\n" -" vec3 delta = mvPosIn - lights[i].pos.xyz;\n" -" float dist = length(delta);\n" -" vec3 deltaNorm = delta / dist;\n" -" float angDot = max(dot(deltaNorm, lights[i].dir.xyz), 0.0);\n" -" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n" -" lights[i].linAtt[1] * dist +\n" -" lights[i].linAtt[0]);\n" -" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n" -" lights[i].angAtt[1] * angDot +\n" -" lights[i].angAtt[0];\n" -" ret += lights[i].color * angAtt * att * max(dot(-deltaNorm, mvNormIn), 0.0);\n" -" }\n" -" \n" -" return clamp(ret, 0.0, 1.0);\n" -"}\n"sv; - -static std::string_view LightingShadowGLSL = -"struct Light\n" -"{\n" -" vec4 pos;\n" -" vec4 dir;\n" -" vec4 color;\n" -" vec4 linAtt;\n" -" vec4 angAtt;\n" -"};\n" -FOG_STRUCT_GLSL -"\n" -"UBINDING2 uniform LightingUniform\n" -"{\n" -" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n" -" vec4 ambient;\n" -" vec4 colorReg0;\n" -" vec4 colorReg1;\n" -" vec4 colorReg2;\n" -" vec4 mulColor;\n" -" vec4 addColor;\n" -" Fog fog;\n" -"};\n" -"\n" -"vec4 LightingShadowFunc(vec3 mvPosIn, vec3 mvNormIn)\n" -"{\n" -" vec2 shadowUV = vtf.extTcgs[0];\n" -" shadowUV.y = 1.0 - shadowUV.y;\n" -" \n" -" vec4 ret = ambient;\n" -" \n" -" vec3 delta = mvPosIn - lights[0].pos.xyz;\n" -" float dist = length(delta);\n" -" vec3 deltaNorm = delta / dist;\n" -" float angDot = max(dot(deltaNorm, lights[0].dir.xyz), 0.0);\n" -" float att = 1.0 / (lights[0].linAtt[2] * dist * dist +\n" -" lights[0].linAtt[1] * dist +\n" -" lights[0].linAtt[0]);\n" -" float angAtt = lights[0].angAtt[2] * angDot * angDot +\n" -" lights[0].angAtt[1] * angDot +\n" -" lights[0].angAtt[0];\n" -" ret += lights[0].color * angAtt * att * max(dot(-deltaNorm, mvNormIn), 0.0) *\n" -" texture(extTex7, shadowUV).r;\n" -" \n" -" for (int i=1 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n" -" {\n" -" vec3 delta = mvPosIn - lights[i].pos.xyz;\n" -" float dist = length(delta);\n" -" vec3 deltaNorm = delta / dist;\n" -" float angDot = max(dot(deltaNorm, lights[i].dir.xyz), 0.0);\n" -" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n" -" lights[i].linAtt[1] * dist +\n" -" lights[i].linAtt[0]);\n" -" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n" -" lights[i].angAtt[1] * angDot +\n" -" lights[i].angAtt[0];\n" -" ret += lights[i].color * angAtt * att * max(dot(-deltaNorm, mvNormIn), 0.0);\n" -" }\n" -" \n" -" return clamp(ret, 0.0, 1.0);\n" -"}\n"sv; - -static std::string_view MainPostGLSL = - "vec4 MainPostFunc(vec4 colorIn)\n" - "{\n" FOG_ALGORITHM_GLSL - "}\n" - "\n"sv; - -static std::string_view ThermalPostGLSL = - "UBINDING2 uniform ThermalUniform\n" - "{\n" - " vec4 tmulColor;\n" - " vec4 taddColor;\n" - "};\n" - "vec4 ThermalPostFunc(vec4 colorIn)\n" - "{\n" - " return texture(extTex7, vtf.extTcgs[0]).rrrr * tmulColor + taddColor;\n" - "}\n" - "\n"sv; - -static std::string_view SolidPostGLSL = - "UBINDING2 uniform SolidUniform\n" - "{\n" - " vec4 solidColor;\n" - "};\n" - "vec4 SolidPostFunc(vec4 colorIn)\n" - "{\n" - " return solidColor;\n" - "}\n" - "\n"sv; - -static std::string_view MBShadowPostGLSL = - "UBINDING2 uniform MBShadowUniform\n" - "{\n" - " vec4 shadowUp;\n" - " float shadowId;\n" - "};\n" - "vec4 MBShadowPostFunc(vec4 colorIn)\n" - "{\n" - " float idTexel = texture(extTex0, vtf.extTcgs[0]).a;\n" - " float sphereTexel = texture(extTex1, vtf.extTcgs[1]).a;\n" - " float fadeTexel = texture(extTex2, vtf.extTcgs[2]).a;\n" - " float val = ((abs(idTexel - shadowId) < 0.001) ?\n" - " (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n" - " sphereTexel * fadeTexel;\n" - " return vec4(0.0, 0.0, 0.0, val);\n" - "}\n" - "\n"sv; - -static std::string_view DisintegratePostGLSL = FOG_STRUCT_GLSL - "UBINDING2 uniform DisintegrateUniform\n" - "{\n" - " vec4 daddColor;\n" - " Fog fog;\n" - "};\n" - "vec4 DisintegratePostFunc(vec4 colorIn)\n" - "{\n" - " vec4 texel0 = texture(extTex7, vtf.extTcgs[0]);\n" - " vec4 texel1 = texture(extTex7, vtf.extTcgs[1]);\n" - " colorIn = mix(vec4(0.0), texel1, texel0);\n" - " colorIn.rgb += daddColor.rgb;\n" FOG_ALGORITHM_GLSL - "}\n" - "\n"sv; - -static std::string_view ThermalColdPostGLSL = - "vec4 ThermalColdPostFunc(vec4 colorIn)\n" - "{\n" - " return colorIn * vec4(0.75);\n" - "}\n" - "\n"sv; - -const hecl::Backend::Function ExtensionLightingFuncsGLSL[] = { - {}, - {LightingGLSL, "LightingFunc"}, - {}, - {LightingGLSL, "LightingFunc"}, - {LightingGLSL, "LightingFunc"}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {LightingShadowGLSL, "LightingShadowFunc"}, - {LightingGLSL, "LightingFunc"}, - {LightingGLSL, "LightingFunc"}, - {LightingGLSL, "LightingFunc"}, - {LightingGLSL, "LightingFunc"}, - {LightingGLSL, "LightingFunc"}, - {LightingGLSL, "LightingFunc"}, - {LightingGLSL, "LightingFunc"}, - {}, - {LightingGLSL, "LightingFunc"}, - {}, - {LightingGLSL, "LightingFunc"}, -}; - -const hecl::Backend::Function ExtensionPostFuncsGLSL[] = { - {}, - {MainPostGLSL, "MainPostFunc"}, - {ThermalPostGLSL, "ThermalPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {SolidPostGLSL, "SolidPostFunc"}, - {SolidPostGLSL, "SolidPostFunc"}, - {SolidPostGLSL, "SolidPostFunc"}, - {SolidPostGLSL, "SolidPostFunc"}, - {SolidPostGLSL, "SolidPostFunc"}, - {SolidPostGLSL, "SolidPostFunc"}, - {MBShadowPostGLSL, "MBShadowPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {DisintegratePostGLSL, "DisintegratePostFunc"}, - {MainPostGLSL, "MainPostFunc"}, - {ThermalColdPostGLSL, "ThermalColdPostFunc"}, - {MainPostGLSL, "MainPostFunc"}, -}; - -} // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShadersHLSL.cpp b/Runtime/Graphics/Shaders/CModelShadersHLSL.cpp deleted file mode 100644 index deaaa52c9..000000000 --- a/Runtime/Graphics/Shaders/CModelShadersHLSL.cpp +++ /dev/null @@ -1,271 +0,0 @@ -#include "CModelShaders.hpp" - -namespace urde { -using namespace std::literals; - -extern const hecl::Backend::Function ExtensionLightingFuncsHLSL[]; -extern const hecl::Backend::Function ExtensionPostFuncsHLSL[]; - -#define FOG_STRUCT_HLSL \ - "struct Fog\n" \ - "{\n" \ - " float4 color;\n" \ - " float A;\n" \ - " float B;\n" \ - " float C;\n" \ - " int mode;\n" \ - "};\n" - -#define FOG_ALGORITHM_HLSL \ - " float fogZ;\n" \ - " float fogF = saturate((fog.A / (fog.B - (1.0 - vtf.mvpPos.z))) - fog.C);\n" \ - " switch (fog.mode)\n" \ - " {\n" \ - " case 2:\n" \ - " fogZ = fogF;\n" \ - " break;\n" \ - " case 4:\n" \ - " fogZ = 1.0 - exp2(-8.0 * fogF);\n" \ - " break;\n" \ - " case 5:\n" \ - " fogZ = 1.0 - exp2(-8.0 * fogF * fogF);\n" \ - " break;\n" \ - " case 6:\n" \ - " fogZ = exp2(-8.0 * (1.0 - fogF));\n" \ - " break;\n" \ - " case 7:\n" \ - " fogF = 1.0 - fogF;\n" \ - " fogZ = exp2(-8.0 * fogF * fogF);\n" \ - " break;\n" \ - " default:\n" \ - " fogZ = 0.0;\n" \ - " break;\n" \ - " }\n" \ - "#ifdef BLEND_DST_ONE\n" \ - " return float4(lerp(colorIn, float4(0.0,0.0,0.0,0.0), saturate(fogZ)).rgb, colorIn.a);\n" \ - "#else\n" \ - " return float4(lerp(colorIn, fog.color, saturate(fogZ)).rgb, colorIn.a);\n" \ - "#endif\n" - -static std::string_view LightingHLSL = -"struct Light\n" -"{\n" -" float4 pos;\n" -" float4 dir;\n" -" float4 color;\n" -" float4 linAtt;\n" -" float4 angAtt;\n" -"};\n" -FOG_STRUCT_HLSL -"\n" -"cbuffer LightingUniform : register(b2)\n" -"{\n" -" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n" -" float4 ambient;\n" -" float4 colorReg0;\n" -" float4 colorReg1;\n" -" float4 colorReg2;\n" -" float4 mulColor;\n" -" float4 addColor;\n" -" Fog fog;\n" -"};\n" -"\n" -"static float4 LightingFunc(float3 mvPosIn, float3 mvNormIn, in VertToFrag vtf)\n" -"{\n" -" float4 ret = ambient;\n" -" \n" -" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n" -" {\n" -" float3 delta = mvPosIn - lights[i].pos.xyz;\n" -" float dist = length(delta);\n" -" float angDot = saturate(dot(normalize(delta), lights[i].dir.xyz));\n" -" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n" -" lights[i].linAtt[1] * dist +\n" -" lights[i].linAtt[0]);\n" -" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n" -" lights[i].angAtt[1] * angDot +\n" -" lights[i].angAtt[0];\n" -" ret += lights[i].color * angAtt * att * saturate(dot(normalize(-delta), mvNormIn));\n" -" }\n" -" \n" -" return saturate(ret);\n" -"}\n"sv; - -static std::string_view LightingShadowHLSL = -"struct Light\n" -"{\n" -" float4 pos;\n" -" float4 dir;\n" -" float4 color;\n" -" float4 linAtt;\n" -" float4 angAtt;\n" -"};\n" -FOG_STRUCT_HLSL -"\n" -"cbuffer LightingUniform : register(b2)\n" -"{\n" -" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n" -" float4 ambient;\n" -" float4 colorReg0;\n" -" float4 colorReg1;\n" -" float4 colorReg2;\n" -" float4 mulColor;\n" -" float4 addColor;\n" -" Fog fog;\n" -"};\n" -"\n" -"static float4 LightingShadowFunc(float3 mvPosIn, float3 mvNormIn, in VertToFrag vtf)\n" -"{\n" -" float4 ret = ambient;\n" -" \n" -" float3 delta = mvPosIn - lights[0].pos.xyz;\n" -" float dist = length(delta);\n" -" float angDot = saturate(dot(normalize(delta), lights[0].dir.xyz));\n" -" float att = 1.0 / (lights[0].linAtt[2] * dist * dist +\n" -" lights[0].linAtt[1] * dist +\n" -" lights[0].linAtt[0]);\n" -" float angAtt = lights[0].angAtt[2] * angDot * angDot +\n" -" lights[0].angAtt[1] * angDot +\n" -" lights[0].angAtt[0];\n" -" ret += lights[0].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn)) *\n" -" extTex7.Sample(clampSamp, vtf.extTcgs[0]).r;\n" -" \n" -" for (int i=1 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n" -" {\n" -" float3 delta = mvPosIn - lights[i].pos.xyz;\n" -" float dist = length(delta);\n" -" float angDot = saturate(dot(normalize(delta), lights[i].dir.xyz));\n" -" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n" -" lights[i].linAtt[1] * dist +\n" -" lights[i].linAtt[0]);\n" -" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n" -" lights[i].angAtt[1] * angDot +\n" -" lights[i].angAtt[0];\n" -" ret += lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn));\n" -" }\n" -" \n" -" return ret;\n" -"}\n"sv; - -static std::string_view MainPostHLSL = - "static float4 MainPostFunc(in VertToFrag vtf, float4 colorIn)\n" - "{\n" FOG_ALGORITHM_HLSL - "}\n" - "\n"sv; - -static std::string_view ThermalPostHLSL = - "cbuffer ThermalUniform : register(b2)\n" - "{\n" - " float4 tmulColor;\n" - " float4 taddColor;\n" - "};\n" - "static float4 ThermalPostFunc(in VertToFrag vtf, float4 colorIn)\n" - "{\n" - " return extTex7.Sample(samp, vtf.extTcgs[0]).rrrr * tmulColor + taddColor;\n" - "}\n" - "\n"sv; - -static std::string_view SolidPostHLSL = - "cbuffer SolidUniform : register(b2)\n" - "{\n" - " float4 solidColor;\n" - "};\n" - "static float4 SolidPostFunc(in VertToFrag vtf, float4 colorIn)\n" - "{\n" - " return solidColor;\n" - "}\n" - "\n"sv; - -static std::string_view MBShadowPostHLSL = - "cbuffer MBShadowUniform : register(b2)\n" - "{\n" - " float4 shadowUp;\n" - " float shadowId;\n" - "};\n" - "static float4 MBShadowPostFunc(in VertToFrag vtf, float4 colorIn)\n" - "{\n" - " float idTexel = extTex0.Sample(samp, vtf.extTcgs[0]).a;\n" - " float sphereTexel = extTex1.Sample(samp, vtf.extTcgs[1]).a;\n" - " float fadeTexel = extTex2.Sample(samp, vtf.extTcgs[2]).a;\n" - " float val = ((abs(idTexel - shadowId) < 0.001) ?\n" - " (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n" - " sphereTexel * fadeTexel;\n" - " return float4(0.0, 0.0, 0.0, val);\n" - "}\n" - "\n"sv; - -static std::string_view DisintegratePostHLSL = FOG_STRUCT_HLSL - "cbuffer DisintegrateUniform : register(b2)\n" - "{\n" - " float4 daddColor;\n" - " Fog fog;\n" - "};\n" - "static float4 DisintegratePostFunc(in VertToFrag vtf, float4 colorIn)\n" - "{\n" - " float4 texel0 = extTex7.Sample(samp, vtf.extTcgs[0]);\n" - " float4 texel1 = extTex7.Sample(samp, vtf.extTcgs[1]);\n" - " colorIn = lerp(float4(0.0,0.0,0.0,0.0), texel1, texel0);\n" - " colorIn.rgb += daddColor.rgb;\n" FOG_ALGORITHM_HLSL - "}\n" - "\n"sv; - -static std::string_view ThermalColdPostHLSL = - "static float4 ThermalColdPostFunc(in VertToFrag vtf, float4 colorIn)\n" - "{\n" - " return colorIn * float4(0.75, 0.75, 0.75, 0.75);\n" - "}\n" - "\n"sv; - -const hecl::Backend::Function ExtensionLightingFuncsHLSL[] = {{}, - {LightingHLSL, "LightingFunc"}, - {}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {LightingShadowHLSL, "LightingShadowFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {}, - {LightingHLSL, "LightingFunc"}, - {}, - {LightingHLSL, "LightingFunc"},}; - -const hecl::Backend::Function ExtensionPostFuncsHLSL[] = { - {}, - {MainPostHLSL, "MainPostFunc"}, - {ThermalPostHLSL, "ThermalPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {SolidPostHLSL, "SolidPostFunc"}, - {SolidPostHLSL, "SolidPostFunc"}, - {SolidPostHLSL, "SolidPostFunc"}, - {SolidPostHLSL, "SolidPostFunc"}, - {SolidPostHLSL, "SolidPostFunc"}, - {SolidPostHLSL, "SolidPostFunc"}, - {MBShadowPostHLSL, "MBShadowPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {DisintegratePostHLSL, "DisintegratePostFunc"}, - {MainPostHLSL, "MainPostFunc"}, - {ThermalColdPostHLSL, "ThermalColdPostFunc"}, - {MainPostHLSL, "MainPostFunc"}, -}; - -} // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShadersMetal.cpp b/Runtime/Graphics/Shaders/CModelShadersMetal.cpp deleted file mode 100644 index 4107e2deb..000000000 --- a/Runtime/Graphics/Shaders/CModelShadersMetal.cpp +++ /dev/null @@ -1,276 +0,0 @@ -#include "CModelShaders.hpp" - -namespace urde { -using namespace std::literals; - -extern const hecl::Backend::Function ExtensionLightingFuncsMetal[]; -extern const hecl::Backend::Function ExtensionPostFuncsMetal[]; - -#define FOG_STRUCT_METAL \ - "struct Fog\n" \ - "{\n" \ - " float4 color;\n" \ - " float A;\n" \ - " float B;\n" \ - " float C;\n" \ - " int mode;\n" \ - "};\n" - -#define FOG_ALGORITHM_METAL \ - " float fogZ;\n" \ - " float fogF = saturate((lu.fog.A / (lu.fog.B - (1.0 - vtf.mvpPos.z))) - lu.fog.C);\n" \ - " switch (lu.fog.mode)\n" \ - " {\n" \ - " case 2:\n" \ - " fogZ = fogF;\n" \ - " break;\n" \ - " case 4:\n" \ - " fogZ = 1.0 - exp2(-8.0 * fogF);\n" \ - " break;\n" \ - " case 5:\n" \ - " fogZ = 1.0 - exp2(-8.0 * fogF * fogF);\n" \ - " break;\n" \ - " case 6:\n" \ - " fogZ = exp2(-8.0 * (1.0 - fogF));\n" \ - " break;\n" \ - " case 7:\n" \ - " fogF = 1.0 - fogF;\n" \ - " fogZ = exp2(-8.0 * fogF * fogF);\n" \ - " break;\n" \ - " default:\n" \ - " fogZ = 0.0;\n" \ - " break;\n" \ - " }\n" \ - "#ifdef BLEND_DST_ONE\n" \ - " return float4(mix(colorIn, float4(0.0), saturate(fogZ)).rgb, colorIn.a);\n" \ - "#else\n" \ - " return float4(mix(colorIn, lu.fog.color, saturate(fogZ)).rgb, colorIn.a);\n" \ - "#endif\n" - -static std::string_view LightingMetal = -"struct Light\n" -"{\n" -" float4 pos;\n" -" float4 dir;\n" -" float4 color;\n" -" float4 linAtt;\n" -" float4 angAtt;\n" -"};\n" -FOG_STRUCT_METAL -"\n" -"struct LightingUniform\n" -"{\n" -" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n" -" float4 ambient;\n" -" float4 colorReg0;\n" -" float4 colorReg1;\n" -" float4 colorReg2;\n" -" float4 mulColor;\n" -" float4 addColor;\n" -" Fog fog;\n" -"};\n" -"\n" -"static float4 LightingFunc(constant LightingUniform& lu, float3 mvPosIn, float3 mvNormIn, thread VertToFrag& vtf)\n" -"{\n" -" float4 ret = lu.ambient;\n" -" \n" -" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n" -" {\n" -" float3 delta = mvPosIn - lu.lights[i].pos.xyz;\n" -" float dist = length(delta);\n" -" float angDot = saturate(dot(normalize(delta), lu.lights[i].dir.xyz));\n" -" float att = 1.0 / (lu.lights[i].linAtt[2] * dist * dist +\n" -" lu.lights[i].linAtt[1] * dist +\n" -" lu.lights[i].linAtt[0]);\n" -" float angAtt = lu.lights[i].angAtt[2] * angDot * angDot +\n" -" lu.lights[i].angAtt[1] * angDot +\n" -" lu.lights[i].angAtt[0];\n" -" ret += lu.lights[i].color * angAtt * att * saturate(dot(normalize(-delta), mvNormIn));\n" -" }\n" -" \n" -" return saturate(ret);\n" -"}\n"sv; - -static std::string_view LightingShadowMetal = -"struct Light\n" -"{\n" -" float4 pos;\n" -" float4 dir;\n" -" float4 color;\n" -" float4 linAtt;\n" -" float4 angAtt;\n" -"};\n" -FOG_STRUCT_METAL -"\n" -"struct LightingUniform\n" -"{\n" -" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n" -" float4 ambient;\n" -" float4 colorReg0;\n" -" float4 colorReg1;\n" -" float4 colorReg2;\n" -" float4 mulColor;\n" -" float4 addColor;\n" -" Fog fog;\n" -"};\n" -"\n" -"static float4 EXTLightingShadowFunc(constant LightingUniform& lu, float3 mvPosIn, float3 mvNormIn,\n" -" thread VertToFrag& vtf, sampler samp, sampler clampSamp, texture2d extTex7)\n" -"{\n" -" float4 ret = lu.ambient;\n" -" \n" -" float3 delta = mvPosIn - lu.lights[0].pos.xyz;\n" -" float dist = length(delta);\n" -" float angDot = saturate(dot(normalize(delta), lu.lights[0].dir.xyz));\n" -" float att = 1.0 / (lu.lights[0].linAtt[2] * dist * dist +\n" -" lu.lights[0].linAtt[1] * dist +\n" -" lu.lights[0].linAtt[0]);\n" -" float angAtt = lu.lights[0].angAtt[2] * angDot * angDot +\n" -" lu.lights[0].angAtt[1] * angDot +\n" -" lu.lights[0].angAtt[0];\n" -" ret += lu.lights[0].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn)) *\n" -" extTex7.sample(clampSamp, vtf.extTcgs0).r;\n" -" \n" -" for (int i=1 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n" -" {\n" -" float3 delta = mvPosIn - lu.lights[i].pos.xyz;\n" -" float dist = length(delta);\n" -" float angDot = saturate(dot(normalize(delta), lu.lights[i].dir.xyz));\n" -" float att = 1.0 / (lu.lights[i].linAtt[2] * dist * dist +\n" -" lu.lights[i].linAtt[1] * dist +\n" -" lu.lights[i].linAtt[0]);\n" -" float angAtt = lu.lights[i].angAtt[2] * angDot * angDot +\n" -" lu.lights[i].angAtt[1] * angDot +\n" -" lu.lights[i].angAtt[0];\n" -" ret += lu.lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn));\n" -" }\n" -" \n" -" return ret;\n" -"}\n"sv; - -static std::string_view MainPostMetal = - "float4 MainPostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, float4 colorIn)\n" - "{\n" FOG_ALGORITHM_METAL - "}\n" - "\n"sv; - -static std::string_view ThermalPostMetal = - "struct ThermalUniform\n" - "{\n" - " float4 tmulColor;\n" - " float4 taddColor;\n" - "};\n" - "static float4 EXTThermalPostFunc(thread VertToFrag& vtf, constant ThermalUniform& lu,\n" - " sampler samp, sampler clampSamp, texture2d extTex7, float4 colorIn)\n" - "{\n" - " return extTex7.sample(samp, vtf.extTcgs0).rrrr * lu.tmulColor + lu.taddColor;\n" - "}\n" - "\n"sv; - -static std::string_view SolidPostMetal = - "struct SolidUniform\n" - "{\n" - " float4 solidColor;\n" - "};\n" - "static float4 SolidPostFunc(thread VertToFrag& vtf, constant SolidUniform& lu, float4 colorIn)\n" - "{\n" - " return lu.solidColor;\n" - "}\n" - "\n"sv; - -static std::string_view MBShadowPostMetal = - "struct MBShadowUniform\n" - "{\n" - " float4 shadowUp;\n" - " float shadowId;\n" - "};\n" - "static float4 EXTMBShadowPostFunc(thread VertToFrag& vtf, constant MBShadowUniform& su, sampler samp,\n" - " sampler clampSamp, texture2d extTex0, texture2d extTex1,\n" - " texture2d extTex2, float4 colorIn)\n" - "{\n" - " float idTexel = extTex0.sample(samp, vtf.extTcgs0).a;\n" - " float sphereTexel = extTex1.sample(samp, vtf.extTcgs1).a;\n" - " float fadeTexel = extTex2.sample(samp, vtf.extTcgs2).a;\n" - " float val = ((fabs(idTexel - su.shadowId) < 0.001) ?\n" - " (dot(vtf.mvNorm.xyz, su.shadowUp.xyz) * su.shadowUp.w) : 0.0) *\n" - " sphereTexel * fadeTexel;\n" - " return float4(0.0, 0.0, 0.0, val);\n" - "}\n" - "\n"sv; - -static std::string_view DisintegratePostMetal = FOG_STRUCT_METAL - "struct DisintegrateUniform\n" - "{\n" - " float4 daddColor;\n" - " Fog fog;\n" - "};\n" - "static float4 EXTDisintegratePostFunc(thread VertToFrag& vtf, constant DisintegrateUniform& lu, sampler samp,\n" - " sampler clampSamp, texture2d extTex7, float4 colorIn)\n" - "{\n" - " float4 texel0 = extTex7.sample(samp, vtf.extTcgs0);\n" - " float4 texel1 = extTex7.sample(samp, vtf.extTcgs1);\n" - " colorIn = mix(float4(0.0), texel1, texel0);\n" - " colorIn.rgb += lu.daddColor.rgb;\n" FOG_ALGORITHM_METAL - "}\n" - "\n"sv; - -static std::string_view ThermalColdPostMetal = - "static float4 ThermalColdPostFunc(thread VertToFrag& vtf, float4 colorIn)\n" - "{\n" - " return colorIn * float4(0.75, 0.75, 0.75, 0.75);\n" - "}\n" - "\n"sv; - -const hecl::Backend::Function ExtensionLightingFuncsMetal[] = {{}, - {LightingMetal, "LightingFunc"}, - {}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {LightingShadowMetal, "EXTLightingShadowFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {}, - {LightingMetal, "LightingFunc"}, - {}, - {LightingMetal, "LightingFunc"},}; - -const hecl::Backend::Function ExtensionPostFuncsMetal[] = { - {}, - {MainPostMetal, "MainPostFunc"}, - {ThermalPostMetal, "EXTThermalPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {SolidPostMetal, "SolidPostFunc"}, - {SolidPostMetal, "SolidPostFunc"}, - {SolidPostMetal, "SolidPostFunc"}, - {SolidPostMetal, "SolidPostFunc"}, - {SolidPostMetal, "SolidPostFunc"}, - {SolidPostMetal, "SolidPostFunc"}, - {MBShadowPostMetal, "EXTMBShadowPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {DisintegratePostMetal, "EXTDisintegratePostFunc"}, - {MainPostMetal, "MainPostFunc"}, - {ThermalColdPostMetal, "ThermalColdPostFunc"}, - {MainPostMetal, "MainPostFunc"}, -}; - -} // namespace urde diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 19d103bcb..4f2961343 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -1081,7 +1081,7 @@ void CGameArea::FillInStaticGeometry(bool textures) { TToken nullModel; inst.m_instance = std::make_unique(nullModel, nullptr, &inst.m_surfaces, matSet, vbo, ibo, - inst.x34_aabb, inst.x0_visorFlags, 0, nullptr); + inst.x34_aabb, inst.x0_visorFlags, 0); } return true; diff --git a/Runtime/World/CScriptPickup.cpp b/Runtime/World/CScriptPickup.cpp index 2c988aa6b..4d8bd1e95 100644 --- a/Runtime/World/CScriptPickup.cpp +++ b/Runtime/World/CScriptPickup.cpp @@ -138,7 +138,7 @@ void CScriptPickup::Touch(CActor& act, CStateManager& mgr) { } } - mgr.GetPlayerState()->InitializePowerUp(x258_itemType, x260_capacity); + mgr.GetPlayerState()->AddPowerUp(x258_itemType, x260_capacity); mgr.GetPlayerState()->IncrPickup(x258_itemType, x25c_amount); mgr.FreeScriptObject(GetUniqueId()); SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); diff --git a/Runtime/World/CScriptPlayerStateChange.cpp b/Runtime/World/CScriptPlayerStateChange.cpp index ff767e300..fb35a34b7 100644 --- a/Runtime/World/CScriptPlayerStateChange.cpp +++ b/Runtime/World/CScriptPlayerStateChange.cpp @@ -19,7 +19,7 @@ void CScriptPlayerStateChange::Accept(IVisitor& visitor) { visitor.Visit(this); void CScriptPlayerStateChange::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { if (GetActive() && msg == EScriptObjectMessage::SetToZero) { - stateMgr.GetPlayerState()->InitializePowerUp(CPlayerState::EItemType(x34_itemType), x3c_itemCapacity); + stateMgr.GetPlayerState()->AddPowerUp(CPlayerState::EItemType(x34_itemType), x3c_itemCapacity); stateMgr.GetPlayerState()->IncrPickup(CPlayerState::EItemType(x34_itemType), x38_itemCount); if (x44_ctrlCmdOpt == EControlCommandOption::Filtered && x40_ctrl == EControl::Filtered) { diff --git a/Shaders/CMakeLists.txt b/Shaders/CMakeLists.txt index a24be6cc2..8b93fcfd8 100644 --- a/Shaders/CMakeLists.txt +++ b/Shaders/CMakeLists.txt @@ -2,7 +2,7 @@ include_directories(../hecl/include ../hecl/extern/boo/include ../hecl/extern/boo/logvisor/include ../hecl/extern/athena/include - ../specter/zeus/include + ../DataSpec ../Runtime) add_shader(CAABoxShader) add_shader(CCameraBlurFilter) @@ -35,3 +35,7 @@ add_special_shader(shader_CFluidPlaneShader shader_CFluidPlaneShaderGLSL.cpp shader_CFluidPlaneShaderHLSL.cpp shader_CFluidPlaneShaderMetal.cpp) +add_special_shader(shader_CModelShaders + shader_CModelShadersGLSL.cpp + shader_CModelShadersHLSL.cpp + shader_CModelShadersMetal.cpp) \ No newline at end of file diff --git a/Shaders/CModelShaders.common.glsl b/Shaders/CModelShaders.common.glsl new file mode 100644 index 000000000..1bf3ae38e --- /dev/null +++ b/Shaders/CModelShaders.common.glsl @@ -0,0 +1,18 @@ +#extension GL_ARB_enhanced_layouts: enable +#extension GL_ARB_shader_image_load_store: enable + +struct VertToFrag { + vec4 mvPos; + vec4 mvNorm; + vec4 color; + vec2 lightmapUv; + vec2 diffuseUv; + vec2 emissiveUv; + vec2 specularUv; + vec2 extendedSpecularUv; + vec2 reflectionUv; + vec2 alphaUv; + vec2 extUvs[3]; + vec2 dynReflectionUvs[2]; + float dynReflectionAlpha; +}; diff --git a/Shaders/CModelShaders.frag.glsl b/Shaders/CModelShaders.frag.glsl new file mode 100644 index 000000000..2c9b48f50 --- /dev/null +++ b/Shaders/CModelShaders.frag.glsl @@ -0,0 +1,348 @@ +#if !defined(URDE_ALPHA_TEST) && defined(GL_ARB_shader_image_load_store) +layout(early_fragment_tests) in; +#endif + +SBINDING(0) in VertToFrag vtf; +TBINDING0 uniform sampler2D lightmap; +TBINDING1 uniform sampler2D diffuse; +TBINDING2 uniform sampler2D emissive; +TBINDING3 uniform sampler2D specular; +TBINDING4 uniform sampler2D extendedSpecular; +TBINDING5 uniform sampler2D reflection; +TBINDING6 uniform sampler2D alpha; +TBINDING7 uniform sampler2D reflectionIndTex; +TBINDING8 uniform sampler2D extTex0; +TBINDING9 uniform sampler2D extTex1; +TBINDING10 uniform sampler2D extTex2; +TBINDING11 uniform sampler2D reflectionTex; + +const vec3 kRGBToYPrime = vec3(0.257, 0.504, 0.098); + +/* +#if defined(ALPHA_%s) +vec3 SampleTexture_%s() { return texture(%s, vtf.%sUv).aaa; } +float SampleTextureAlpha_%s() { return texture(%s, vtf.%sUv).a; } +#else +vec3 SampleTexture_%s() { return texture(%s, vtf.%sUv).rgb; } +float SampleTextureAlpha_%s() { return dot(texture(%s, vtf.%sUv).rgb, kRGBToYPrime); } +#endif + */ + +#if defined(ALPHA_lightmap) +vec3 SampleTexture_lightmap() { return texture(lightmap, vtf.lightmapUv).aaa; } +float SampleTextureAlpha_lightmap() { return texture(lightmap, vtf.lightmapUv).a; } +#else +vec3 SampleTexture_lightmap() { return texture(lightmap, vtf.lightmapUv).rgb; } +float SampleTextureAlpha_lightmap() { return dot(texture(lightmap, vtf.lightmapUv).rgb, kRGBToYPrime); } +#endif + +#if defined(ALPHA_diffuse) +vec3 SampleTexture_diffuse() { return texture(diffuse, vtf.diffuseUv).aaa; } +float SampleTextureAlpha_diffuse() { return texture(diffuse, vtf.diffuseUv).a; } +#else +vec3 SampleTexture_diffuse() { return texture(diffuse, vtf.diffuseUv).rgb; } +float SampleTextureAlpha_diffuse() { return dot(texture(diffuse, vtf.diffuseUv).rgb, kRGBToYPrime); } +#endif + +#if defined(ALPHA_emissive) +vec3 SampleTexture_emissive() { return texture(emissive, vtf.emissiveUv).aaa; } +float SampleTextureAlpha_emissive() { return texture(emissive, vtf.emissiveUv).a; } +#else +vec3 SampleTexture_emissive() { return texture(emissive, vtf.emissiveUv).rgb; } +float SampleTextureAlpha_emissive() { return dot(texture(emissive, vtf.emissiveUv).rgb, kRGBToYPrime); } +#endif + +#if defined(ALPHA_specular) +vec3 SampleTexture_specular() { return texture(specular, vtf.specularUv).aaa; } +float SampleTextureAlpha_specular() { return texture(specular, vtf.specularUv).a; } +#else +vec3 SampleTexture_specular() { return texture(specular, vtf.specularUv).rgb; } +float SampleTextureAlpha_specular() { return dot(texture(specular, vtf.specularUv).rgb, kRGBToYPrime); } +#endif + +#if defined(ALPHA_extendedSpecular) +vec3 SampleTexture_extendedSpecular() { return texture(extendedSpecular, vtf.extendedSpecularUv).aaa; } +float SampleTextureAlpha_extendedSpecular() { return texture(extendedSpecular, vtf.extendedSpecularUv).a; } +#else +vec3 SampleTexture_extendedSpecular() { return texture(extendedSpecular, vtf.extendedSpecularUv).rgb; } +float SampleTextureAlpha_extendedSpecular() { return dot(texture(extendedSpecular, vtf.extendedSpecularUv).rgb, kRGBToYPrime); } +#endif + +#if defined(ALPHA_reflection) +vec3 SampleTexture_reflection() { return texture(reflection, vtf.reflectionUv).aaa; } +float SampleTextureAlpha_reflection() { return texture(reflection, vtf.reflectionUv).a; } +#else +vec3 SampleTexture_reflection() { return texture(reflection, vtf.reflectionUv).rgb; } +float SampleTextureAlpha_reflection() { return dot(texture(reflection, vtf.reflectionUv).rgb, kRGBToYPrime); } +#endif + +#if defined(ALPHA_alpha) +vec3 SampleTexture_alpha() { return texture(alpha, vtf.alphaUv).aaa; } +float SampleTextureAlpha_alpha() { return texture(alpha, vtf.alphaUv).a; } +#else +vec3 SampleTexture_alpha() { return texture(alpha, vtf.alphaUv).rgb; } +float SampleTextureAlpha_alpha() { return dot(texture(alpha, vtf.alphaUv).rgb, kRGBToYPrime); } +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_DISINTEGRATE) +struct Fog { + vec4 color; + float A; + float B; + float C; + int mode; +}; +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) +struct Light { + vec4 pos; + vec4 dir; + vec4 color; + vec4 linAtt; + vec4 angAtt; +}; + +UBINDING2 uniform LightingUniform { + Light lights[URDE_MAX_LIGHTS]; + vec4 ambient; + vec4 colorReg0; + vec4 colorReg1; + vec4 colorReg2; + vec4 mulColor; + vec4 addColor; + Fog fog; +}; +#else +const vec4 colorReg0 = vec4(1.0, 1.0, 1.0, 1.0); +const vec4 colorReg1 = vec4(1.0, 1.0, 1.0, 1.0); +const vec4 colorReg2 = vec4(1.0, 1.0, 1.0, 1.0); +#endif + +#if defined(URDE_LIGHTING) +vec3 LightingFunc(vec3 mvPosIn, vec3 mvNormIn) { + vec4 ret = ambient; + + for (int i = 0; i < URDE_MAX_LIGHTS; ++i) { + vec3 delta = mvPosIn - lights[i].pos.xyz; + float dist = length(delta); + vec3 deltaNorm = delta / dist; + float angDot = max(dot(deltaNorm, lights[i].dir.xyz), 0.0); + float att = 1.0 / (lights[i].linAtt[2] * dist * dist + + lights[i].linAtt[1] * dist + + lights[i].linAtt[0]); + float angAtt = lights[i].angAtt[2] * angDot * angDot + + lights[i].angAtt[1] * angDot + + lights[i].angAtt[0]; + ret += lights[i].color * angAtt * att * max(dot(-deltaNorm, mvNormIn), 0.0); + } + + return clamp(ret.rgb, vec3(0.0), vec3(1.0)); +} +#endif + +#if defined(URDE_THERMAL_HOT) +vec3 LightingFunc(vec3 mvPosIn, vec3 mvNormIn) { + return vec3(1.0,1.0,1.0); +} +UBINDING2 uniform ThermalUniform { + vec4 tmulColor; + vec4 taddColor; +}; +#endif + +#if defined(URDE_THERMAL_COLD) +vec3 LightingFunc(vec3 mvPosIn, vec3 mvNormIn) { + return vec3(1.0,1.0,1.0); +} +#endif + +#if defined(URDE_SOLID) +vec3 LightingFunc(vec3 mvPosIn, vec3 mvNormIn) { + return vec3(1.0,1.0,1.0); +} +UBINDING2 uniform SolidUniform { + vec4 solidColor; +}; +#endif + +#if defined(URDE_MB_SHADOW) +vec3 LightingFunc(vec3 mvPosIn, vec3 mvNormIn) { + return vec3(1.0,1.0,1.0); +} +UBINDING2 uniform MBShadowUniform { + vec4 shadowUp; + float shadowId; +}; +#endif + +#if defined(URDE_LIGHTING_SHADOW) +vec3 LightingFunc(vec3 mvPosIn, vec3 mvNormIn) { + vec2 shadowUV = vtf.extUvs[0]; + shadowUV.y = 1.0 - shadowUV.y; + + vec4 ret = ambient; + + vec3 delta = mvPosIn - lights[0].pos.xyz; + float dist = length(delta); + vec3 deltaNorm = delta / dist; + float angDot = max(dot(deltaNorm, lights[0].dir.xyz), 0.0); + float att = 1.0 / (lights[0].linAtt[2] * dist * dist + + lights[0].linAtt[1] * dist + + lights[0].linAtt[0]); + float angAtt = lights[0].angAtt[2] * angDot * angDot + + lights[0].angAtt[1] * angDot + + lights[0].angAtt[0]; + ret += lights[0].color * angAtt * att * max(dot(-deltaNorm, mvNormIn), 0.0) * + texture(extTex0, shadowUV).r; + + for (int i = 1; i < URDE_MAX_LIGHTS; ++i) { + vec3 delta = mvPosIn - lights[i].pos.xyz; + float dist = length(delta); + vec3 deltaNorm = delta / dist; + float angDot = max(dot(deltaNorm, lights[i].dir.xyz), 0.0); + float att = 1.0 / (lights[i].linAtt[2] * dist * dist + + lights[i].linAtt[1] * dist + + lights[i].linAtt[0]); + float angAtt = lights[i].angAtt[2] * angDot * angDot + + lights[i].angAtt[1] * angDot + + lights[i].angAtt[0]; + ret += lights[i].color * angAtt * att * max(dot(-deltaNorm, mvNormIn), 0.0); + } + + return clamp(ret.rgb, vec3(0.0), vec3(1.0)); +} +#endif + +#if defined(URDE_DISINTEGRATE) +UBINDING2 uniform DisintegrateUniform { + vec4 daddColor; + Fog fog; +}; +vec3 LightingFunc(vec3 mvPosIn, vec3 mvNormIn) { + return vec3(1.0,1.0,1.0); +} +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_DISINTEGRATE) +vec4 FogFunc(vec4 colorIn) { + float fogZ; + float fogF = clamp((fog.A / (fog.B - gl_FragCoord.z)) - fog.C, 0.0, 1.0); + switch (fog.mode) { + case 2: + fogZ = fogF; + break; + case 4: + fogZ = 1.0 - exp2(-8.0 * fogF); + break; + case 5: + fogZ = 1.0 - exp2(-8.0 * fogF * fogF); + break; + case 6: + fogZ = exp2(-8.0 * (1.0 - fogF)); + break; + case 7: + fogF = 1.0 - fogF; + fogZ = exp2(-8.0 * fogF * fogF); + break; + default: + fogZ = 0.0; + break; + } +#ifdef BLEND_DST_ONE + return vec4(mix(colorIn, vec4(0.0), clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a); +#else + return vec4(mix(colorIn, fog.color, clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a); +#endif +} +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) +vec4 PostFunc(vec4 colorIn) { + return FogFunc(colorIn) * mulColor + addColor; +} +#endif + +#if defined(URDE_THERMAL_HOT) +vec4 PostFunc(vec4 colorIn) { + return texture(extTex0, vtf.extUvs[0]).rrrr * tmulColor + taddColor; +} +#endif + +#if defined(URDE_THERMAL_COLD) +vec4 PostFunc(vec4 colorIn) { + return colorIn * vec4(0.75); +} +#endif + +#if defined(URDE_SOLID) +vec4 PostFunc(vec4 colorIn) { + return solidColor; +} +#endif + +#if defined(URDE_MB_SHADOW) +vec4 PostFunc(vec4 colorIn) { + float idTexel = texture(extTex0, vtf.extUvs[0]).a; + float sphereTexel = texture(extTex1, vtf.extUvs[1]).a; + float fadeTexel = texture(extTex2, vtf.extUvs[2]).a; + float val = ((abs(idTexel - shadowId) < 0.001) ? + (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) * + sphereTexel * fadeTexel; + return vec4(0.0, 0.0, 0.0, val); +} +#endif + +#if defined(URDE_DISINTEGRATE) +vec4 PostFunc(vec4 colorIn) { + vec4 texel0 = texture(extTex0, vtf.extUvs[0]); + vec4 texel1 = texture(extTex0, vtf.extUvs[1]); + colorIn = mix(vec4(0.0), texel1, texel0); + colorIn.rgb += daddColor.rgb; + return FogFunc(colorIn); +} +#endif + +#if defined(URDE_REFLECTION_SIMPLE) +vec3 ReflectionFunc() { return texture(reflectionTex, vtf.dynReflectionUvs[1]).rgb * vtf.dynReflectionAlpha; } +#elif defined(URDE_REFLECTION_INDIRECT) +vec3 ReflectionFunc() { return texture(reflectionTex, (texture(reflectionIndTex, vtf.dynReflectionUvs[0]).ab - + vec2(0.5, 0.5)) * vec2(0.5, 0.5) + vtf.dynReflectionUvs[1]).rgb * vtf.dynReflectionAlpha; } +#else +vec3 ReflectionFunc() { return vec3(0.0, 0.0, 0.0); } +#endif + +layout(location=0) out vec4 colorOut; +void main() { + vec3 lighting = LightingFunc(vtf.mvPos.xyz, vtf.mvNorm.xyz); + vec4 tmp; +#if defined(URDE_DIFFUSE_ONLY) + tmp.rgb = SampleTexture_diffuse(); + tmp.a = SampleTextureAlpha_alpha(); +#elif defined(RETRO_SHADER) + tmp.rgb = (SampleTexture_lightmap() * colorReg1.rgb + lighting) * SampleTexture_diffuse() + + SampleTexture_emissive() + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha(); +#elif defined(RETRO_DYNAMIC_SHADER) + tmp.rgb = (SampleTexture_lightmap() * colorReg1.rgb + lighting) * SampleTexture_diffuse() * colorReg1.rgb + + SampleTexture_emissive() * colorReg1.rgb + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha(); +#elif defined(RETRO_DYNAMIC_ALPHA_SHADER) + tmp.rgb = (SampleTexture_lightmap() * colorReg1.rgb + lighting) * SampleTexture_diffuse() * colorReg1.rgb + + SampleTexture_emissive() * colorReg1.rgb + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha() * colorReg1.a; +#elif defined(RETRO_DYNAMIC_CHARACTER_SHADER) + tmp.rgb = (SampleTexture_lightmap() + lighting) * SampleTexture_diffuse() + + SampleTexture_emissive() * colorReg1.rgb + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha(); +#endif + colorOut = PostFunc(tmp); +#if defined(URDE_ALPHA_TEST) + if (colorOut.a < 0.25) + discard; +#endif +} diff --git a/Shaders/CModelShaders.vert.glsl b/Shaders/CModelShaders.vert.glsl new file mode 100644 index 000000000..7024d1525 --- /dev/null +++ b/Shaders/CModelShaders.vert.glsl @@ -0,0 +1,61 @@ +UBINDING0 uniform HECLVertUniform { +#if URDE_SKIN_SLOTS + mat4 objs[URDE_SKIN_SLOTS]; + mat4 objsInv[URDE_SKIN_SLOTS]; +#endif + mat4 mv; + mat4 mvInv; + mat4 proj; +}; + +struct HECLTCGMatrix { + mat4 mtx; + mat4 postMtx; +}; +UBINDING1 uniform HECLTexMtxUniform { + HECLTCGMatrix texMtxs[8]; +}; + +UBINDING3 uniform HECLReflectMtx { + mat4 indMtx; + mat4 reflectMtx; + float reflectAlpha; +}; + +layout(location=0) in vec3 posIn; +layout(location=1) in vec3 normIn; +#if URDE_COL_SLOTS +layout(location=2) in vec4 colIn[URDE_COL_SLOTS]; +#endif +#if URDE_UV_SLOTS +layout(location=2 + URDE_COL_SLOTS) in vec2 uvIn[URDE_UV_SLOTS]; +#endif +#if URDE_WEIGHT_SLOTS +layout(location=2 + URDE_COL_SLOTS + URDE_UV_SLOTS) in vec4 weightIn[URDE_WEIGHT_SLOTS]; +#endif + +SBINDING(0) out VertToFrag vtf; +void main() { +#if URDE_SKIN_SLOTS + vec4 objPos = vec4(0.0,0.0,0.0,0.0); + vec4 objNorm = vec4(0.0,0.0,0.0,0.0); + for (int i = 0; i < URDE_SKIN_SLOTS; ++i) { + objPos += (objs[i] * vec4(posIn, 1.0)) * weightIn[i / 4][i % 4]; + objNorm += (objsInv[i] * vec4(normIn, 1.0)) * weightIn[i / 4][i % 4]; + } + objPos[3] = 1.0; + objNorm = vec4(normalize(objNorm.xyz), 0.0); + vtf.mvPos = mv * objPos; + vtf.mvNorm = vec4(normalize((mvInv * objNorm).xyz), 0.0); + gl_Position = proj * vtf.mvPos; +#else + vec4 objPos = vec4(posIn, 1.0); + vec4 objNorm = vec4(normIn, 0.0); + vtf.mvPos = mv * objPos; + vtf.mvNorm = mvInv * objNorm; + gl_Position = proj * vtf.mvPos; +#endif + + vec4 tmpProj; + URDE_TCG_EXPR +} diff --git a/Shaders/shader_CModelShaders.hpp b/Shaders/shader_CModelShaders.hpp new file mode 100644 index 000000000..63a0bf496 --- /dev/null +++ b/Shaders/shader_CModelShaders.hpp @@ -0,0 +1,59 @@ +#pragma once +#include "hecl/PipelineBase.hpp" +#include "hecl/hecl.hpp" +#include "DataSpec/DNAMP1/CMDLMaterials.hpp" + +struct SModelShadersInfo { + uint64_t m_hash; + using Material = DataSpec::DNAMP1::HMDLMaterialSet::Material; + const Material& m_material; + const hecl::Backend::ShaderTag& m_tag; + const hecl::Backend::ExtensionSlot& m_extension; + std::vector m_vtxFmtData; + boo::VertexFormatInfo m_vtxFmt; + boo::AdditionalPipelineInfo m_additionalInfo; + + explicit SModelShadersInfo(const Material& material, + const hecl::Backend::ShaderTag& tag, + const hecl::Backend::ExtensionSlot& extension) + : m_material(material), m_tag(tag), m_extension(extension) { + m_hash = m_tag.val64(); + hecl::hash_combine_impl(m_hash, std::hash()(m_extension.hash())); + + m_vtxFmtData = tag.vertexFormat(); + m_vtxFmt = boo::VertexFormatInfo(m_vtxFmtData.size(), m_vtxFmtData.data()); + + m_additionalInfo = m_tag.additionalInfo(extension, material.blendFactors()); + } + + static constexpr bool HasHash = true; + uint64_t Hash() const { return m_hash; } +}; + +class Shader_CModelShaders : public hecl::GeneralShader { + const SModelShadersInfo& m_info; +public: + Shader_CModelShaders(const SModelShadersInfo& in) + : m_info(in) + , VtxFmt(in.m_vtxFmt) + , PipelineInfo(in.m_additionalInfo) {} + + const boo::VertexFormatInfo VtxFmt; + const boo::AdditionalPipelineInfo PipelineInfo; + static constexpr bool HasHash = true; + uint64_t Hash() const { return m_info.m_hash; } + const SModelShadersInfo& info() const { return m_info; } +}; + +template +class StageObject_CModelShaders : public hecl::StageBinary { + static std::string BuildShader(const SModelShadersInfo& in); + +public: + StageObject_CModelShaders(hecl::StageConverter& conv, hecl::FactoryCtx& ctx, + const Shader_CModelShaders& in) + : hecl::StageBinary(conv, ctx, hecl::StageSourceText(BuildShader(in.info()))) {} +}; + +#define UNIVERSAL_PIPELINES_shader_CModelShaders ::Shader_CModelShaders +#define STAGES_shader_CModelShaders(P, S) ::StageObject_CModelShaders, diff --git a/Shaders/shader_CModelShadersGLSL.cpp b/Shaders/shader_CModelShadersGLSL.cpp new file mode 100644 index 000000000..8afa6c90b --- /dev/null +++ b/Shaders/shader_CModelShadersGLSL.cpp @@ -0,0 +1,217 @@ +#include +#include +#include +#include "shader_CModelShaders.hpp" +#include "Runtime/Graphics/Shaders/CModelShaders.hpp" + +extern "C" const uint8_t CMODELSHADERS_COMMON_GLSL[]; +extern "C" size_t CMODELSHADERS_COMMON_GLSL_SZ; +static std::string_view CMODELSHADERS_COMMON_GLSL_SV((char*)CMODELSHADERS_COMMON_GLSL, CMODELSHADERS_COMMON_GLSL_SZ); + +extern "C" const uint8_t CMODELSHADERS_VERT_GLSL[]; +extern "C" size_t CMODELSHADERS_VERT_GLSL_SZ; +static std::string_view CMODELSHADERS_VERT_GLSL_SV((char*)CMODELSHADERS_VERT_GLSL, CMODELSHADERS_VERT_GLSL_SZ); + +extern "C" const uint8_t CMODELSHADERS_FRAG_GLSL[]; +extern "C" size_t CMODELSHADERS_FRAG_GLSL_SZ; +static std::string_view CMODELSHADERS_FRAG_GLSL_SV((char*)CMODELSHADERS_FRAG_GLSL, CMODELSHADERS_FRAG_GLSL_SZ); + +using BlendMaterial = SModelShadersInfo::Material::BlendMaterial; +using TexCoordSource = BlendMaterial::TexCoordSource; + +static std::string_view EmitTexGenSource2(TexCoordSource src) { + switch (src) { + case TexCoordSource::Position: + return "objPos.xy"sv; + case TexCoordSource::Normal: + return "objNorm.xy"sv; + case TexCoordSource::Tex0: + return "uvIn[0]"sv; + case TexCoordSource::Tex1: + return "uvIn[1]"sv; + case TexCoordSource::Tex2: + return "uvIn[2]"sv; + case TexCoordSource::Tex3: + return "uvIn[3]"sv; + case TexCoordSource::Tex4: + return "uvIn[4]"sv; + case TexCoordSource::Tex5: + return "uvIn[5]"sv; + case TexCoordSource::Tex6: + return "uvIn[6]"sv; + case TexCoordSource::Tex7: + return "uvIn[7]"sv; + default: + assert(false && "Unknown source type"); + break; + } + return {}; +} + +static std::string_view EmitTexGenSource4(TexCoordSource src) { + switch (src) { + case TexCoordSource::Position: + return "vec4(objPos.xyz, 1.0)"sv; + case TexCoordSource::Normal: + return "vec4(objNorm.xyz, 1.0)"sv; + case TexCoordSource::Tex0: + return "vec4(uvIn[0], 0.0, 1.0)"sv; + case TexCoordSource::Tex1: + return "vec4(uvIn[1], 0.0, 1.0)"sv; + case TexCoordSource::Tex2: + return "vec4(uvIn[2], 0.0, 1.0)"sv; + case TexCoordSource::Tex3: + return "vec4(uvIn[3], 0.0, 1.0)"sv; + case TexCoordSource::Tex4: + return "vec4(uvIn[4], 0.0, 1.0)"sv; + case TexCoordSource::Tex5: + return "vec4(uvIn[5], 0.0, 1.0)"sv; + case TexCoordSource::Tex6: + return "vec4(uvIn[6], 0.0, 1.0)"sv; + case TexCoordSource::Tex7: + return "vec4(uvIn[7], 0.0, 1.0)"sv; + default: + assert(false && "Unknown source type"); + break; + } + return {}; +} + +static std::string _BuildVS(const SModelShadersInfo& info) { + std::stringstream vertOut; + vertOut << CMODELSHADERS_COMMON_GLSL_SV; + vertOut << "#define URDE_COL_SLOTS "sv << unsigned(info.m_tag.getColorCount()) << '\n'; + vertOut << "#define URDE_UV_SLOTS "sv << unsigned(info.m_tag.getUvCount()) << '\n'; + vertOut << "#define URDE_SKIN_SLOTS "sv << unsigned(info.m_tag.getSkinSlotCount()) << '\n'; + vertOut << "#define URDE_WEIGHT_SLOTS "sv << unsigned(info.m_tag.getWeightCount()) << '\n'; + vertOut << "#define URDE_TCG_EXPR "sv; + + using UVAnimType = BlendMaterial::UVAnimType; + using PassType = BlendMaterial::PassType; + int mtxIdx = 0; + for (const auto& chunk : info.m_material.chunks) { + if (auto passChunk = chunk.get_if()) { + if (passChunk->type != PassType::IndirectTex) { + std::string_view tpStr = BlendMaterial::PassTypeToString(passChunk->type); + if (passChunk->uvAnimType == UVAnimType::Invalid) { + vertOut << "vtf."sv << tpStr << "Uv = "sv << EmitTexGenSource2(passChunk->source) << ";"sv; + } else { + vertOut << "tmpProj = texMtxs["sv << mtxIdx << "].postMtx * vec4("sv << + (passChunk->shouldNormalizeUv() ? "normalize"sv : ""sv) << "((texMtxs["sv << mtxIdx << "].mtx * "sv << + EmitTexGenSource4(passChunk->source) << ").xyz), 1.0);"sv << + "vtf."sv << tpStr << "Uv = (tmpProj / tmpProj.w).xy;"sv; + } + } + } else if (auto clrChunk = chunk.get_if()) { + std::string_view tpStr = BlendMaterial::PassTypeToString(clrChunk->type); + vertOut << "vtf."sv << tpStr << "Uv = vec2(0.0,0.0);"sv; + } + } + if (!info.m_extension.noReflection && info.m_tag.getReflectionType() != hecl::Backend::ReflectionType::None) + vertOut << "vtf.dynReflectionUvs[0] = normalize((indMtx * vec4(objPos.xyz, 1.0)).xz) * vec2(0.5, 0.5) + vec2(0.5, 0.5);" + "vtf.dynReflectionUvs[1] = (reflectMtx * vec4(objPos.xyz, 1.0)).xy;" + "vtf.dynReflectionAlpha = reflectAlpha;"; + + for (int i = 0; i < info.m_extension.texCount; ++i) { + const auto& extTex = info.m_extension.texs[i]; + if (extTex.mtxIdx < 0) + vertOut << "vtf.extUvs["sv << i << "] = "sv << EmitTexGenSource2(extTex.src) << ";"sv; + else + vertOut << "tmpProj = texMtxs["sv << unsigned(extTex.mtxIdx) << "].postMtx * vec4("sv << + (extTex.normalize ? "normalize"sv : ""sv) << "((texMtxs["sv << unsigned(extTex.mtxIdx) << "].mtx * "sv << + EmitTexGenSource4(extTex.src) << ").xyz), 1.0);"sv << + "vtf.extUvs["sv << i << "] = (tmpProj / tmpProj.w).xy;"sv; + } + vertOut << '\n'; + + vertOut << CMODELSHADERS_VERT_GLSL_SV; + return vertOut.str(); +} + +static std::string _BuildFS(const SModelShadersInfo& info) { + std::stringstream fragOut; + fragOut << CMODELSHADERS_COMMON_GLSL_SV; + fragOut << "#define URDE_MAX_LIGHTS " _XSTR(URDE_MAX_LIGHTS) "\n"; + fragOut << "#define " << info.m_extension.shaderMacro << "\n"; + + using ShaderType = BlendMaterial::ShaderType; + switch (info.m_material.shaderType) { + case ShaderType::RetroShader: + fragOut << "#define RETRO_SHADER\n"; break; + case ShaderType::RetroDynamicShader: + fragOut << "#define RETRO_DYNAMIC_SHADER\n"; break; + case ShaderType::RetroDynamicAlphaShader: + fragOut << "#define RETRO_DYNAMIC_ALPHA_SHADER\n"; break; + case ShaderType::RetroDynamicCharacterShader: + fragOut << "#define RETRO_DYNAMIC_CHARACTER_SHADER\n"; break; + default: + assert(false && "Unknown shader type"); + break; + } + + fragOut << "#define BLEND_SRC_"sv << hecl::Backend::BlendFactorToDefine( + hecl::Backend::BlendFactor(info.m_additionalInfo.srcFac), hecl::Backend::BlendFactor::One) << '\n'; + fragOut << "#define BLEND_DST_"sv << hecl::Backend::BlendFactorToDefine( + hecl::Backend::BlendFactor(info.m_additionalInfo.dstFac), hecl::Backend::BlendFactor::Zero) << '\n'; + + using PassType = BlendMaterial::PassType; + for (const auto& chunk : info.m_material.chunks) { + if (auto passChunk = chunk.get_if()) { + if (passChunk->alpha) { + std::string_view tpStr = BlendMaterial::PassTypeToString(passChunk->type); + fragOut << "#define ALPHA_" << tpStr << '\n'; + } + } else if (auto clrChunk = chunk.get_if()) { + if (clrChunk->type == PassType::Alpha) + fragOut << "#define ALPHA_alpha\n"; + } + } + + if (info.m_tag.getAlphaTest() || info.m_extension.forceAlphaTest) + fragOut << "#define URDE_ALPHA_TEST\n"; + + if (info.m_extension.diffuseOnly) + fragOut << "#define URDE_DIFFUSE_ONLY\n"; + + if (!info.m_extension.noReflection) { + if (info.m_tag.getReflectionType() == hecl::Backend::ReflectionType::Indirect) + fragOut << "#define URDE_REFLECTION_INDIRECT\n"sv; + else if (info.m_tag.getReflectionType() == hecl::Backend::ReflectionType::Simple) + fragOut << "#define URDE_REFLECTION_SIMPLE\n"sv; + } + + fragOut << CMODELSHADERS_FRAG_GLSL_SV; + return fragOut.str(); +} + +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildVS(in); +} +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildVS(in); +} +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildVS(in); +} + +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildFS(in); +} +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildFS(in); +} +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildFS(in); +} diff --git a/Shaders/shader_CModelShadersHLSL.cpp b/Shaders/shader_CModelShadersHLSL.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Shaders/shader_CModelShadersMetal.cpp b/Shaders/shader_CModelShadersMetal.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/hecl b/hecl index a80592249..43536e34f 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit a80592249b8a6ace071249824a55a1e979ae3e3d +Subproject commit 43536e34f1d820c7b88c71f77c3ccd7b3d7bc35c diff --git a/specter b/specter index b32f4975a..3d0d62e03 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit b32f4975a8f0e5f282339b162069d1fbc15c298d +Subproject commit 3d0d62e0324bc881f4ae3058b8ec89c8a2c95a66