Lightmap rendering

This commit is contained in:
Jack Andersen 2015-09-17 09:50:43 -10:00
parent 8b653fd7f6
commit da24b39957
9 changed files with 126 additions and 50 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@ -1 +1 @@
Subproject commit b2b3d9c34daa2e2c0e4b8cfd9c7d775f61d4bf56
Subproject commit 893e16c79579499d3834873c99d3fba5c1236898