mirror of https://github.com/AxioDL/metaforce.git
Lightmap rendering
This commit is contained in:
parent
8b653fd7f6
commit
da24b39957
|
@ -80,6 +80,14 @@ void InitGeomBlenderContext(HECL::BlenderConnection::PyOutStream& os,
|
|||
" face.smooth = True\n"
|
||||
"\n"
|
||||
" return face, ret_mesh\n"
|
||||
"\n"
|
||||
"def expand_lightmap_triangle(uva, uvb, uvc):\n"
|
||||
" result = ([uva[0],uva[1]], [uvb[0],uvb[1]], [uvc[0],uvc[1]])\n"
|
||||
" if uva == uvb:\n"
|
||||
" result[1][0] += 0.005\n"
|
||||
" if uva == uvc:\n"
|
||||
" result[2][1] -= 0.005\n"
|
||||
" return result\n"
|
||||
"\n";
|
||||
|
||||
/* Link master shader library */
|
||||
|
|
|
@ -589,12 +589,14 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||
for (unsigned j=0 ; j<matUVCount ; ++j)
|
||||
{
|
||||
if (j==0 && matShortUVs)
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
|
||||
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
|
||||
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j],
|
||||
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
|
||||
os.format(" uv_tri = expand_lightmap_triangle(suv_list[%u], suv_list[%u], suv_list[%u])\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[0]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[1]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[2]\n",
|
||||
primVerts[c%3].uvs[j], primVerts[(c+2)%3].uvs[j], primVerts[(c+1)%3].uvs[j],
|
||||
primVerts[c%3].pos, j,
|
||||
primVerts[(c+2)%3].pos, j,
|
||||
primVerts[(c+1)%3].pos, j);
|
||||
else
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
|
@ -621,12 +623,14 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||
for (unsigned j=0 ; j<matUVCount ; ++j)
|
||||
{
|
||||
if (j==0 && matShortUVs)
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
|
||||
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
|
||||
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j],
|
||||
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j]);
|
||||
os.format(" uv_tri = expand_lightmap_triangle(suv_list[%u], suv_list[%u], suv_list[%u])\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[0]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[1]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[2]\n",
|
||||
primVerts[c%3].uvs[j], primVerts[(c+1)%3].uvs[j], primVerts[(c+2)%3].uvs[j],
|
||||
primVerts[c%3].pos, j,
|
||||
primVerts[(c+1)%3].pos, j,
|
||||
primVerts[(c+2)%3].pos, j);
|
||||
else
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
|
@ -666,12 +670,14 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||
for (unsigned j=0 ; j<matUVCount ; ++j)
|
||||
{
|
||||
if (j==0 && matShortUVs)
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
|
||||
primVerts[0].pos, j, primVerts[0].uvs[j],
|
||||
primVerts[1].pos, j, primVerts[1].uvs[j],
|
||||
primVerts[2].pos, j, primVerts[2].uvs[j]);
|
||||
os.format(" uv_tri = expand_lightmap_triangle(suv_list[%u], suv_list[%u], suv_list[%u])\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[0]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[1]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[2]\n",
|
||||
primVerts[0].uvs[j], primVerts[1].uvs[j], primVerts[2].uvs[j],
|
||||
primVerts[0].pos, j,
|
||||
primVerts[1].pos, j,
|
||||
primVerts[2].pos, j);
|
||||
else
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
|
@ -710,12 +716,14 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
|
|||
for (unsigned j=0 ; j<matUVCount ; ++j)
|
||||
{
|
||||
if (j==0 && matShortUVs)
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
|
||||
firstPrimVert.pos, j, firstPrimVert.uvs[j],
|
||||
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
|
||||
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
|
||||
os.format(" uv_tri = expand_lightmap_triangle(suv_list[%u], suv_list[%u], suv_list[%u])\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[0]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[1]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_tri[2]\n",
|
||||
firstPrimVert.uvs[j], primVerts[c%3].uvs[j], primVerts[(c+1)%3].uvs[j],
|
||||
firstPrimVert.pos, j,
|
||||
primVerts[c%3].pos, j,
|
||||
primVerts[(c+1)%3].pos, j);
|
||||
else
|
||||
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
|
||||
|
|
|
@ -18,7 +18,6 @@ void MaterialSet::RegisterMaterialProps(Stream& out)
|
|||
"bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n"
|
||||
"bpy.types.Material.retro_samus_reflection_indirect = bpy.props.BoolProperty(name='Retro: Samus Reflection Indirect Texture')\n"
|
||||
"bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n"
|
||||
"bpy.types.Material.retro_lightmap = bpy.props.StringProperty(name='Retro: Lightmap')\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
|
@ -323,19 +322,6 @@ static void AddAlphaCombiner(Stream& out, enum CombinerType type,
|
|||
out << "alpha_combiner_nodes.append(combiner_node)\n\n";
|
||||
}
|
||||
|
||||
static void AddLightmap(Stream& out, const char* tex, unsigned& c_combiner_idx)
|
||||
{
|
||||
out << "world_light_node = new_nodetree.nodes.new('ShaderNodeRGB')\n"
|
||||
"gridder.place_node(world_light_node, 1)\n"
|
||||
"world_light_node.label = 'WORLD_LIGHTING'\n"
|
||||
"world_light_node.outputs[0].default_value = (1.0,1.0,1.0,1.0)\n";
|
||||
AddColorCombiner(out, COMB_MULT, tex, "world_light_node.outputs[0]", nullptr);
|
||||
AddColorCombiner(out, COMB_ADD,
|
||||
"color_combiner_nodes[-1].outputs[0]",
|
||||
"material_node.outputs['Color']", nullptr);
|
||||
c_combiner_idx += 2;
|
||||
}
|
||||
|
||||
static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg,
|
||||
GX::TevKColorSel kcolor,
|
||||
const MaterialSet::Material::TEVStageTexInfo& stageTex,
|
||||
|
@ -669,9 +655,12 @@ void _ConstructMaterial(Stream& out,
|
|||
if (material.flags.lightmap() && material.tevStages[0].colorInB() == GX::CC_C1)
|
||||
{
|
||||
if (material.tevStageTexInfo[0].texSlot != 0xff)
|
||||
out << "new_material.retro_lightmap = tex_maps[0].name\n"
|
||||
out << "new_material.hecl_lightmap = tex_maps[0].name\n"
|
||||
"tex_maps[0].image.use_fake_user = True\n";
|
||||
AddLightmap(out, "texture_nodes[0].outputs['Color']", c_combiner_idx);
|
||||
out << "world_light_node = new_nodetree.nodes.new('ShaderNodeRGB')\n"
|
||||
"gridder.place_node(world_light_node, 1)\n"
|
||||
"world_light_node.label = 'WORLD_LIGHTING'\n"
|
||||
"world_light_node.outputs[0].default_value = (1.0,1.0,1.0,1.0)\n";
|
||||
strncpy(c_regs[GX::TEVREG1], "world_light_node.outputs[0]", 64);
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,28 @@ void PAKBridge::build()
|
|||
mlvl.read(rs);
|
||||
m_areaDeps.reserve(mlvl.areaCount);
|
||||
unsigned layerIdx = 0;
|
||||
|
||||
/* Pre-pass: find duplicate area names */
|
||||
std::unordered_map<HECL::SystemString, std::pair<atUint32, atUint32>> dupeTracker;
|
||||
dupeTracker.reserve(mlvl.areas.size());
|
||||
for (const MLVL::Area& area : mlvl.areas)
|
||||
{
|
||||
const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
||||
if (areaNameEnt)
|
||||
{
|
||||
STRG areaName;
|
||||
PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
|
||||
areaName.read(rs);
|
||||
HECL::SystemString name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||
auto search = dupeTracker.find(name);
|
||||
if (search != dupeTracker.end())
|
||||
++search->second.first;
|
||||
else
|
||||
dupeTracker[name] = std::make_pair(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Main-pass: index areas */
|
||||
for (const MLVL::Area& area : mlvl.areas)
|
||||
{
|
||||
Area& areaDeps = m_areaDeps[area.areaMREAId];
|
||||
|
@ -137,6 +159,13 @@ void PAKBridge::build()
|
|||
PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
|
||||
areaName.read(rs);
|
||||
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||
auto search = dupeTracker.find(areaDeps.name);
|
||||
if (search != dupeTracker.end() && search->second.first > 1)
|
||||
{
|
||||
char num[16];
|
||||
snprintf(num, 16, " (%d)", search->second.second++);
|
||||
areaDeps.name += num;
|
||||
}
|
||||
|
||||
/* Trim possible trailing whitespace */
|
||||
#if HECL_UCS2
|
||||
|
|
|
@ -12,6 +12,10 @@ void MREA::ReadBabeDeadToBlender_1_2(HECL::BlenderConnection::PyOutStream& os,
|
|||
atUint32 bdMagic = rs.readUint32Big();
|
||||
if (bdMagic != 0xBABEDEAD)
|
||||
Log.report(LogVisor::FatalError, "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"
|
||||
"bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n";
|
||||
for (atUint32 s=0 ; s<2 ; ++s)
|
||||
{
|
||||
atUint32 lightCount = rs.readUint32Big();
|
||||
|
@ -22,8 +26,10 @@ void MREA::ReadBabeDeadToBlender_1_2(HECL::BlenderConnection::PyOutStream& os,
|
|||
switch (light.lightType)
|
||||
{
|
||||
case BabeDeadLight::LightLocalAmbient:
|
||||
os.format("bpy.context.scene.world.horizon_color = (%f,%f,%f)\n",
|
||||
light.color.vec[0], light.color.vec[1], light.color.vec[2]);
|
||||
os.format("bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n"
|
||||
"bg_node.inputs[1].default_value = %f\n",
|
||||
light.color.vec[0], light.color.vec[1], light.color.vec[2],
|
||||
light.q / 8.0);
|
||||
continue;
|
||||
case BabeDeadLight::LightDirectional:
|
||||
os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n"
|
||||
|
@ -54,23 +60,30 @@ void MREA::ReadBabeDeadToBlender_1_2(HECL::BlenderConnection::PyOutStream& os,
|
|||
os.format("lamp.retro_layer = %u\n"
|
||||
"lamp.use_nodes = True\n"
|
||||
"falloff_node = lamp.node_tree.nodes.new('ShaderNodeLightFalloff')\n"
|
||||
"lamp.energy = 0.0\n"
|
||||
"falloff_node.inputs[0].default_value = %f\n"
|
||||
"lamp.node_tree.nodes['Emission'].inputs[0].default_value = (%f,%f,%f,1.0)\n"
|
||||
"lamp_obj.hide_render = True\n"
|
||||
"hue_sat_node = lamp.node_tree.nodes.new('ShaderNodeHueSaturation')\n"
|
||||
"hue_sat_node.inputs[1].default_value = 1.25\n"
|
||||
"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"
|
||||
"\n", s, light.q,
|
||||
"\n", s, light.q / 8.0,
|
||||
light.color.vec[0], light.color.vec[1], light.color.vec[2],
|
||||
light.position.vec[0], light.position.vec[1], light.position.vec[2]);
|
||||
|
||||
switch (light.falloff)
|
||||
{
|
||||
case BabeDeadLight::FalloffConstant:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
os << "falloff_node.inputs[0].default_value *= 75.0\n"
|
||||
"lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
break;
|
||||
case BabeDeadLight::FalloffLinear:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
break;
|
||||
case BabeDeadLight::FalloffQuadratic:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,28 @@ void PAKBridge::build()
|
|||
mlvl.read(rs);
|
||||
m_areaDeps.reserve(mlvl.areaCount);
|
||||
unsigned layerIdx = 0;
|
||||
|
||||
/* Pre-pass: find duplicate area names */
|
||||
std::unordered_map<HECL::SystemString, std::pair<atUint32, atUint32>> dupeTracker;
|
||||
dupeTracker.reserve(mlvl.areas.size());
|
||||
for (const MLVL::Area& area : mlvl.areas)
|
||||
{
|
||||
const DNAMP1::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
||||
if (areaNameEnt)
|
||||
{
|
||||
STRG areaName;
|
||||
PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
|
||||
areaName.read(rs);
|
||||
HECL::SystemString name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||
auto search = dupeTracker.find(name);
|
||||
if (search != dupeTracker.end())
|
||||
++search->second.first;
|
||||
else
|
||||
dupeTracker[name] = std::make_pair(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Main-pass: index areas */
|
||||
for (const MLVL::Area& area : mlvl.areas)
|
||||
{
|
||||
Area& areaDeps = m_areaDeps[area.areaMREAId];
|
||||
|
@ -136,6 +158,13 @@ void PAKBridge::build()
|
|||
PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
|
||||
areaName.read(rs);
|
||||
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||
auto search = dupeTracker.find(areaDeps.name);
|
||||
if (search != dupeTracker.end() && search->second.first > 1)
|
||||
{
|
||||
char num[16];
|
||||
snprintf(num, 16, " (%d)", search->second.second++);
|
||||
areaDeps.name += num;
|
||||
}
|
||||
|
||||
/* Trim possible trailing whitespace */
|
||||
#if HECL_UCS2
|
||||
|
|
|
@ -48,7 +48,7 @@ class CMain : public boo::IApplicationCallback
|
|||
CMemorySys x6c_memSys;
|
||||
CTweaks x70_tweaks;
|
||||
EGameplayResult xe4_gameplayResult;
|
||||
bool xe8_finished = false;
|
||||
bool xe8_b24_finished = false;
|
||||
|
||||
public:
|
||||
CMain();
|
||||
|
|
|
@ -154,9 +154,9 @@ int CMain::RsMain(int argc, const boo::SystemChar* argv[])
|
|||
g_TweakManager->ReadFromMemoryCard("AudioTweaks");
|
||||
FillInAssetIDs();
|
||||
TOneStatic<CGameArchitectureSupport> archSupport;
|
||||
while (!xe8_finished)
|
||||
while (!xe8_b24_finished)
|
||||
{
|
||||
xe8_finished = archSupport->Update();
|
||||
xe8_b24_finished = archSupport->Update();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit b2b3d9c34daa2e2c0e4b8cfd9c7d775f61d4bf56
|
||||
Subproject commit 893e16c79579499d3834873c99d3fba5c1236898
|
Loading…
Reference in New Issue