Refactor for blender 2.8 and new shader model

This commit is contained in:
Jack Andersen 2019-05-07 17:50:21 -10:00
parent 1f10769af3
commit 233d13ceb9
67 changed files with 2827 additions and 2105 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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";

View File

@ -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]);

View File

@ -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<MaterialSet> matSets;
#if 0
matSets.reserve(mesh.materialSets.size());
{
hecl::Frontend::Frontend FE;
for (const std::vector<Material>& 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<MaterialSet> matSets;
matSets.reserve(mesh.materialSets.size());
{
hecl::Frontend::Frontend FE;
for (const std::vector<Material>& mset : mesh.materialSets) {
matSets.emplace_back();
MaterialSet& targetMSet = matSets.back();
std::vector<hecl::ProjectPath> 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<Material>& 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<std::vector<uint8_t>>& secsOut, const hecl::Proje
surfCount += mesh.surfaces.size();
surfToGlobalMats.reserve(surfCount);
hecl::Frontend::Frontend FE;
size_t endOff = 0;
std::vector<hecl::ProjectPath> texPaths;
std::vector<hecl::Backend::GX> setBackends;
for (const Mesh& mesh : meshes) {
if (mesh.materialSets.size()) {
std::vector<size_t> meshToGlobalMats;
@ -1630,28 +1594,24 @@ bool WriteMREASecs(std::vector<std::vector<uint8_t>>& 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<Material::PASS>()) {
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<std::vector<uint8_t>>& 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<hecl::ProjectPath> texPaths;
for (const Mesh& mesh : meshes) {
if (mesh.materialSets.size()) {
std::vector<size_t> meshToGlobalMats;
@ -1933,30 +1891,16 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& 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);

View File

@ -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 <class PAKRouter, class MaterialSet>
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 <class PAKRouter, class MaterialSet, class RigPair, class SurfaceHeader>

View File

@ -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

View File

@ -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";
}

18
DataSpec/DNACommon/GX.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "GX.hpp"
namespace GX {
template <>
void Color::Enumerate<athena::io::DNA<athena::Big>::Read>(typename Read::StreamT& reader) {
reader.readUBytesToBuf(&num, 4);
}
template <>
void Color::Enumerate<athena::io::DNA<athena::Big>::Write>(typename Write::StreamT& writer) {
writer.writeUBytes(reinterpret_cast<const atUint8*>(&num), 4);
}
template <>
void Color::Enumerate<athena::io::DNA<athena::Big>::BinarySize>(typename BinarySize::StreamT& s) {
s += 4;
}
}

View File

@ -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<athena::Big> {
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;

View File

@ -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);

View File

@ -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();

View File

@ -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";

View File

@ -322,7 +322,7 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::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();

View File

@ -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<CINF>::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()); }

View File

@ -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<DNACMDL::Mesh::SkinBind> 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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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<std::string, int32_t>& iprops,
const std::vector<hecl::ProjectPath>& texPathsIn, std::vector<hecl::ProjectPath>& texPathsOut,
Material(const hecl::blender::Material& material,
std::vector<hecl::ProjectPath>& texPathsOut,
int colorCount, bool lightmapUVs, bool matrixSkinning);
};
Vector<Material, AT_DNA_COUNT(head.materialCount)> materials;
@ -528,29 +529,114 @@ struct HMDLMaterialSet : BigDNA {
static constexpr bool OneSection() { return false; }
AT_DECL_DNA
MaterialSet::MaterialSetHead head;
Value<atUint32> materialCount = 0;
Vector<atUint32, AT_DNA_COUNT(materialCount)> materialEndOffs;
struct Material : BigDNA {
AT_DECL_DNA
MaterialSet::Material::Flags flags;
Value<atUint32> textureCount = 0;
Vector<atUint32, AT_DNA_COUNT(textureCount)> textureIdxs;
using BlendMaterial = hecl::blender::Material;
Vector<atUint32, AT_DNA_COUNT(flags.samusReflectionIndirectTexture())> indTexSlot;
struct PASS : hecl::TypedRecordBigDNA<BlendMaterial::ChunkType::TexturePass> {
AT_DECL_EXPLICIT_DNA
Value<BlendMaterial::PassType> type;
UniqueID32 texId;
Value<BlendMaterial::TexCoordSource> source;
Value<BlendMaterial::UVAnimType> uvAnimType;
Value<float> uvAnimParms[9] = {};
Value<bool> 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<BlendMaterial::ChunkType::ColorPass> {
AT_DECL_DNA
Value<BlendMaterial::PassType> type;
Value<atVec4f> color;
CLR() = default;
explicit CLR(const BlendMaterial::CLR& clr) : type(clr.type), color(clr.color.val) {}
};
using Chunk = hecl::TypedVariantBigDNA<PASS, CLR>;
Value<atUint32> uvAnimsSize = 4;
Value<atUint32> uvAnimsCount = 0;
Vector<MaterialSet::Material::UVAnimation, AT_DNA_COUNT(uvAnimsCount)> 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<atUint64> hash;
Value<BlendMaterial::ShaderType> shaderType;
Value<atUint32> chunkCount;
Vector<Chunk, AT_DNA_COUNT(chunkCount)> chunks;
Value<BlendMaterial::BlendMode> blendMode = BlendMaterial::BlendMode::Opaque;
std::pair<hecl::Backend::BlendFactor, hecl::Backend::BlendFactor>
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<std::string, int32_t>& iprops, const std::vector<hecl::ProjectPath>& texPaths);
Material(const hecl::blender::Material& mat);
};
Vector<Material, AT_DNA_COUNT(head.materialCount)> materials;
Vector<Material, AT_DNA_COUNT(materialCount)> materials;
};
} // namespace DataSpec::DNAMP1
AT_SPECIALIZE_TYPED_VARIANT_BIGDNA(DataSpec::DNAMP1::HMDLMaterialSet::Material::PASS,
DataSpec::DNAMP1::HMDLMaterialSet::Material::CLR)

View File

@ -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 <class Op>
void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) {
Do<Op>({"xf[0]"}, xf[0], s);
Do<Op>({"xf[1]"}, xf[1], s);
Do<Op>({"xf[2]"}, xf[2], s);
Do<Op>({"halfExtent"}, halfExtent, s);
Do<Op>({"isLeaf"}, isLeaf, s);
if (isLeaf) {
if (!leafData)
leafData.reset(new LeafData);
Do<Op>({"leafData"}, *leafData, s);
} else {
if (!left)
left.reset(new Node);
Do<Op>({"left"}, *left, s);
if (!right)
right.reset(new Node);
Do<Op>({"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);

View File

@ -91,4 +91,27 @@ struct DCLN : BigDNA {
static bool Cook(const hecl::ProjectPath& outPath, const std::vector<Mesh>& meshes);
};
template <class Op>
void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) {
Do<Op>({"xf[0]"}, xf[0], s);
Do<Op>({"xf[1]"}, xf[1], s);
Do<Op>({"xf[2]"}, xf[2], s);
Do<Op>({"halfExtent"}, halfExtent, s);
Do<Op>({"isLeaf"}, isLeaf, s);
if (isLeaf) {
if (!leafData)
leafData.reset(new LeafData);
Do<Op>({"leafData"}, *leafData, s);
} else {
if (!left)
left.reset(new Node);
Do<Op>({"left"}, *left, s);
if (!right)
right.reset(new Node);
Do<Op>({"right"}, *right, s);
}
}
AT_SPECIALIZE_DNA(DCLN::Collision::Node)
} // namespace DataSpec::DNAMP1

View File

@ -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"

View File

@ -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]);
}

View File

@ -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<hecl::ProjectPath, bool>& 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<hecl::ProjectPath, bool>& 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<urde::SObjectTag> 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 */

View File

@ -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);
};

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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<CINF>::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()); }

View File

@ -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"

View File

@ -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();

View File

@ -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<CINF>::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) {

View File

@ -87,8 +87,6 @@ void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter<PAKBridge>& 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<PAKBridge>& 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"

View File

@ -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();

View File

@ -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<urde::SObjectTag>& 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<urde::SObjectTag>& listOut
std::vector<hecl::ProjectPath> 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<urde::SObjectTag> addedTags;
std::vector<std::pair<urde::SObjectTag, std::string>> 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<urde::SObjectTag> 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<urde::SObjectTag> 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<std::mutex> 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<std::mutex> 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");

View File

@ -36,10 +36,9 @@ struct SpecBase : hecl::Database::IDataSpec {
bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& 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;

View File

@ -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<hecl::ProjectPath> 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<hecl::Database::IDataSpec> {
return std::make_unique<SpecMP1>(&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<hecl::Database::IDataSpec> {
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

View File

@ -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<hecl::Database::IDataSpec> {
return std::make_unique<SpecMP2>(&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<hecl::Database::IDataSpec> {
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

View File

@ -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<hecl::Database::IDataSpec> {
return std::make_unique<SpecMP3>(&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<hecl::Database::IDataSpec> {
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

View File

@ -14,7 +14,7 @@ CToken ProjectResourcePool::GetObj(std::string_view name) {
hecl::ProjectPath path(*m_parent.project(), name);
SObjectTag tag =
static_cast<ProjectResourceFactoryBase&>(x18_factory).TagFromPath(path, hecl::blender::SharedBlenderToken);
static_cast<ProjectResourceFactoryBase&>(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<ProjectResourceFactoryBase&>(x18_factory).TagFromPath(path, hecl::blender::SharedBlenderToken);
static_cast<ProjectResourceFactoryBase&>(x18_factory).TagFromPath(path);
if (tag)
return CSimplePool::GetObj(tag, pvxfer);

View File

@ -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());

View File

@ -96,11 +96,11 @@ protected:
bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) {
return static_cast<DataSpec::SpecBase&>(*m_cookSpec).waitForTagReady(tag, pathOut);
}
SObjectTag TagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const {
return static_cast<DataSpec::SpecBase&>(*m_cookSpec).tagFromPath(path, btok);
SObjectTag TagFromPath(const hecl::ProjectPath& path) const {
return static_cast<DataSpec::SpecBase&>(*m_cookSpec).tagFromPath(path);
}
SObjectTag BuildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const {
return static_cast<DataSpec::SpecBase&>(*m_cookSpec).buildTagFromPath(path, btok);
SObjectTag BuildTagFromPath(const hecl::ProjectPath& path) const {
return static_cast<DataSpec::SpecBase&>(*m_cookSpec).buildTagFromPath(path);
}
void GetTagListForFile(const char* pakName, std::vector<SObjectTag>& out) const {
return static_cast<DataSpec::SpecBase&>(*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(); }

View File

@ -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)

View File

@ -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() {

View File

@ -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<u32, u32>& p) { x180_scanCompletionRate = p; }

View File

@ -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);

View File

@ -168,7 +168,7 @@ void Buckets::Init() {
CBooRenderer::CAreaListItem::CAreaListItem(const std::vector<CMetroidModelInstance>* geom,
const CAreaRenderOctTree* octTree,
std::vector<TCachedToken<CTexture>>&& textures,
std::unordered_map<CAssetId, TCachedToken<CTexture>>&& textures,
std::vector<CBooModel*>&& 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<boo::ITexture> 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<boo::ITexture> 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<CMetroidModelInstance>* g
const CAreaRenderOctTree* octTree, int areaIdx, const SShader* shaderSet) {
auto search = FindStaticGeometry(geometry);
if (search == x1c_areaListItems.end()) {
std::vector<TCachedToken<CTexture>> textures;
std::unordered_map<CAssetId, TCachedToken<CTexture>> textures;
std::vector<CBooModel*> models;
if (geometry->size()) {
(*geometry)[0].m_instance->MakeTexturesFromMats(textures, xc_store);

View File

@ -58,7 +58,7 @@ class CBooRenderer final : public IRenderer {
const std::vector<CMetroidModelInstance>* x0_geometry;
const CAreaRenderOctTree* x4_octTree;
/* originally auto_ptrs of vectors */
std::vector<TCachedToken<CTexture>> x8_textures;
std::unordered_map<CAssetId, TCachedToken<CTexture>> x8_textures;
std::vector<CBooModel*> 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<CMetroidModelInstance>* geom, const CAreaRenderOctTree* octTree,
std::vector<TCachedToken<CTexture>>&& textures, std::vector<CBooModel*>&& models, int areaIdx,
const SShader* shaderSet);
std::unordered_map<CAssetId, TCachedToken<CTexture>>&& textures, std::vector<CBooModel*>&& models,
int areaIdx, const SShader* shaderSet);
~CAreaListItem();
};
@ -109,6 +109,7 @@ class CBooRenderer final : public IRenderer {
boo::ObjToken<boo::ITexture> m_clearTexture;
boo::ObjToken<boo::ITexture> m_blackTexture;
boo::ObjToken<boo::ITexture> m_whiteTexture;
std::unordered_map<zeus::CColor, boo::ObjToken<boo::ITexture>> m_colorTextures;
boo::ObjToken<boo::ITextureR> x14c_reflectionTex;
// boo::ITextureS* x150_mirrorRamp = nullptr;
@ -278,6 +279,8 @@ public:
const boo::ObjToken<boo::ITexture>& GetBlackTexture() { return m_blackTexture; }
const boo::ObjToken<boo::ITexture>& GetWhiteTexture() { return m_whiteTexture; }
boo::ObjToken<boo::ITexture> 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() {

View File

@ -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

View File

@ -75,7 +75,6 @@ struct CBooSurface {
};
using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet;
using UVAnimation = DataSpec::DNAMP1::MaterialSet::Material::UVAnimation;
struct GeometryUniformLayout {
boo::ObjToken<boo::IGraphicsBufferD> m_sharedBuffer[2];
@ -96,7 +95,7 @@ struct GeometryUniformLayout {
};
struct SShader {
std::vector<TCachedToken<CTexture>> x0_textures;
std::unordered_map<CAssetId, TCachedToken<CTexture>> x0_textures;
std::unordered_map<int, CModelShaders::ShaderPipelines> m_shaders;
MaterialSet m_matSet;
rstl::optional<GeometryUniformLayout> m_geomLayout;
@ -134,7 +133,7 @@ private:
const GeometryUniformLayout* m_geomLayout;
int m_matSetIdx = -1;
const std::unordered_map<int, CModelShaders::ShaderPipelines>* m_pipelines;
std::vector<TCachedToken<CTexture>> x1c_textures;
std::unordered_map<CAssetId, TCachedToken<CTexture>> 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<boo::IGraphicsBufferS> m_staticVbo;
boo::ObjToken<boo::IGraphicsBufferS> m_staticIbo;
boo::ObjToken<boo::ITexture> m_txtrOverrides[8];
boo::ObjToken<boo::ITexture> m_lastDrawnShadowMap;
boo::ObjToken<boo::ITexture> m_lastDrawnOneTexture;
@ -192,11 +189,12 @@ public:
~CBooModel();
CBooModel(TToken<CModel>& token, CModel* parent, std::vector<CBooSurface>* surfaces, SShader& shader,
const boo::ObjToken<boo::IGraphicsBufferS>& vbo, const boo::ObjToken<boo::IGraphicsBufferS>& ibo,
const zeus::CAABox& aabb, u8 renderMask, int numInsts, const boo::ObjToken<boo::ITexture> txtrOverrides[8]);
const zeus::CAABox& aabb, u8 renderMask, int numInsts);
static void MakeTexturesFromMats(const MaterialSet& matSet, std::vector<TCachedToken<CTexture>>& toksOut,
static void MakeTexturesFromMats(const MaterialSet& matSet,
std::unordered_map<CAssetId, TCachedToken<CTexture>>& toksOut,
IObjectStore& store);
void MakeTexturesFromMats(std::vector<TCachedToken<CTexture>>& toksOut, IObjectStore& store);
void MakeTexturesFromMats(std::unordered_map<CAssetId, TCachedToken<CTexture>>& toksOut, IObjectStore& store);
bool IsOpaque() const { return x3c_firstSortedSurface == nullptr; }
void ActivateLights(const std::vector<CLight>& 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<CBooModel> MakeNewInstance(int shaderIdx, int subInsts,
const boo::ObjToken<boo::ITexture> txtrOverrides[8] = nullptr,
bool lockParent = true);
std::unique_ptr<CBooModel> MakeNewInstance(int shaderIdx, int subInsts, bool lockParent = true);
void UpdateLastFrame() const { const_cast<CModel&>(*this).x38_lastFrame = CGraphics::GetFrameCounter(); }
size_t GetPoolVertexOffset(size_t idx) const;

View File

@ -141,8 +141,7 @@ CBooModel::~CBooModel() {
CBooModel::CBooModel(TToken<CModel>& token, CModel* parent, std::vector<CBooSurface>* surfaces, SShader& shader,
const boo::ObjToken<boo::IGraphicsBufferS>& vbo, const boo::ObjToken<boo::IGraphicsBufferS>& ibo,
const zeus::CAABox& aabb, u8 renderMask, int numInsts,
const boo::ObjToken<boo::ITexture> 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<CModel>& token, CModel* parent, std::vector<CBooSurf
, x41_mask(renderMask)
, m_staticVbo(vbo)
, m_staticIbo(ibo) {
if (txtrOverrides)
for (int i = 0; i < 8; ++i)
m_txtrOverrides[i] = txtrOverrides[i];
if (!g_FirstModel)
g_FirstModel = this;
else {
@ -291,10 +286,6 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) {
/* Binding for each surface */
newInst.m_shaderDataBindings.reserve(x0_surfaces->size());
boo::ObjToken<boo::ITexture> 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<boo::ITexture> 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<boo::ITexture> overtex = m_txtrOverrides[texCount]) {
texs[texCount++] = overtex;
} else if (g_DummyTextures) {
texs[texCount++] = g_Renderer->x220_sphereRamp.get();
} else {
TCachedToken<CTexture>& tex = x1c_textures[idx];
if (boo::ObjToken<boo::ITexture> btex = tex.GetObj()->GetBooTexture())
texs[texCount++] = btex;
boo::ObjToken<boo::ITexture> 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<MaterialSet::Material::PASS>()) {
auto search = x1c_textures.find(pass->texId.toUint32());
boo::ObjToken<boo::ITexture> 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<MaterialSet::Material::CLR>()) {
boo::ObjToken<boo::ITexture> 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<boo::ITexture>* 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<TCachedToken<CTexture>>& toksOut,
void CBooModel::MakeTexturesFromMats(const MaterialSet& matSet,
std::unordered_map<CAssetId, TCachedToken<CTexture>>& 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<MaterialSet::Material::PASS>()) {
toksOut.emplace(std::make_pair(pass->texId.toUint32(), store.GetObj({SBIG('TXTR'), pass->texId.toUint32()})));
}
}
}
}
void CBooModel::MakeTexturesFromMats(std::vector<TCachedToken<CTexture>>& toksOut, IObjectStore& store) {
void CBooModel::MakeTexturesFromMats(std::unordered_map<CAssetId, TCachedToken<CTexture>>& 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<CTexture>& tex : const_cast<std::vector<TCachedToken<CTexture>>&>(x1c_textures)) {
tex.Lock();
if (!tex.IsLoaded())
for (auto& tex : const_cast<std::unordered_map<CAssetId, TCachedToken<CTexture>>&>(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<CBooModel*>(this)->m_instances.clear();
for (TCachedToken<CTexture>& tex : const_cast<std::vector<TCachedToken<CTexture>>&>(x1c_textures))
tex.Unlock();
for (auto& tex : const_cast<std::unordered_map<CAssetId, TCachedToken<CTexture>>&>(x1c_textures))
tex.second.Unlock();
const_cast<CBooModel*>(this)->x40_24_texturesLoaded = false;
}
void CBooModel::SyncLoadTextures() const {
if (!x40_24_texturesLoaded) {
for (TCachedToken<CTexture>& tex : const_cast<std::vector<TCachedToken<CTexture>>&>(x1c_textures))
tex.GetObj();
for (auto& tex : const_cast<std::unordered_map<CAssetId, TCachedToken<CTexture>>&>(x1c_textures))
tex.second.GetObj();
const_cast<CBooModel*>(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<zeus::CMatrix4f&>(*bufOut);
zeus::CMatrix4f& postMtxOut = reinterpret_cast<zeus::CMatrix4f&>(*(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<MaterialSet::Material::PASS>()) {
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<boo::IGraphicsBufferD> 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<CBooModel> CModel::MakeNewInstance(int shaderIdx, int subInsts,
const boo::ObjToken<boo::ITexture> txtrOverrides[8],
bool lockParent) {
std::unique_ptr<CBooModel> CModel::MakeNewInstance(int shaderIdx, int subInsts, bool lockParent) {
if (shaderIdx >= x18_matSets.size())
shaderIdx = 0;
auto ret = std::make_unique<CBooModel>(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<u8[]>&& in, u32 /* dataLen */, IObjectStore* stor
const float* aabbPtr = reinterpret_cast<const float*>(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<CTexture>& tex : x0_textures)
tex.Unlock();
for (auto& tex : x0_textures)
tex.second.Unlock();
}
void CBooModel::VerifyCurrentShader(int shaderIdx) {

View File

@ -54,142 +54,138 @@ void CModelShaders::LightingUniform::ActivateLights(const std::vector<CLight>& 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

View File

@ -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 <array>
#define URDE_MAX_LIGHTS 8
@ -88,7 +89,8 @@ public:
using ShaderPipelinesData = std::array<boo::ObjToken<boo::IShaderPipeline>, EExtendedShader::MAX>;
using ShaderPipelines = std::shared_ptr<ShaderPipelinesData>;
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<uint64_t, ShaderPipelines> g_ShaderPipelines;

View File

@ -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

View File

@ -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

View File

@ -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<float> 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<float> 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<float> extTex0, texture2d<float> extTex1,\n"
" texture2d<float> 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<float> 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

View File

@ -1081,7 +1081,7 @@ void CGameArea::FillInStaticGeometry(bool textures) {
TToken<CModel> nullModel;
inst.m_instance = std::make_unique<CBooModel>(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;

View File

@ -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);

View File

@ -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) {

View File

@ -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)

View File

@ -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;
};

View File

@ -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
}

View File

@ -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
}

View File

@ -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<boo::VertexElementDescriptor> 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<uint64_t>()(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 <typename P, typename S>
class StageObject_CModelShaders : public hecl::StageBinary<P, S> {
static std::string BuildShader(const SModelShadersInfo& in);
public:
StageObject_CModelShaders(hecl::StageConverter<P, S>& conv, hecl::FactoryCtx& ctx,
const Shader_CModelShaders& in)
: hecl::StageBinary<P, S>(conv, ctx, hecl::StageSourceText<P, S>(BuildShader(in.info()))) {}
};
#define UNIVERSAL_PIPELINES_shader_CModelShaders ::Shader_CModelShaders
#define STAGES_shader_CModelShaders(P, S) ::StageObject_CModelShaders<P, S>,

View File

@ -0,0 +1,217 @@
#include <cstdint>
#include <cstdlib>
#include <sstream>
#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<SModelShadersInfo::Material::PASS>()) {
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<SModelShadersInfo::Material::CLR>()) {
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<SModelShadersInfo::Material::PASS>()) {
if (passChunk->alpha) {
std::string_view tpStr = BlendMaterial::PassTypeToString(passChunk->type);
fragOut << "#define ALPHA_" << tpStr << '\n';
}
} else if (auto clrChunk = chunk.get_if<SModelShadersInfo::Material::CLR>()) {
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<hecl::PlatformType::OpenGL, hecl::PipelineStage::Vertex>::BuildShader(
const SModelShadersInfo& in) {
return _BuildVS(in);
}
template <>
std::string StageObject_CModelShaders<hecl::PlatformType::Vulkan, hecl::PipelineStage::Vertex>::BuildShader(
const SModelShadersInfo& in) {
return _BuildVS(in);
}
template <>
std::string StageObject_CModelShaders<hecl::PlatformType::NX, hecl::PipelineStage::Vertex>::BuildShader(
const SModelShadersInfo& in) {
return _BuildVS(in);
}
template <>
std::string StageObject_CModelShaders<hecl::PlatformType::OpenGL, hecl::PipelineStage::Fragment>::BuildShader(
const SModelShadersInfo& in) {
return _BuildFS(in);
}
template <>
std::string StageObject_CModelShaders<hecl::PlatformType::Vulkan, hecl::PipelineStage::Fragment>::BuildShader(
const SModelShadersInfo& in) {
return _BuildFS(in);
}
template <>
std::string StageObject_CModelShaders<hecl::PlatformType::NX, hecl::PipelineStage::Fragment>::BuildShader(
const SModelShadersInfo& in) {
return _BuildFS(in);
}

View File

View File

2
hecl

@ -1 +1 @@
Subproject commit a80592249b8a6ace071249824a55a1e979ae3e3d
Subproject commit 43536e34f1d820c7b88c71f77c3ccd7b3d7bc35c

@ -1 +1 @@
Subproject commit b32f4975a8f0e5f282339b162069d1fbc15c298d
Subproject commit 3d0d62e0324bc881f4ae3058b8ec89c8a2c95a66