Work on level light baking

This commit is contained in:
James Lambert 2023-06-24 21:11:15 -06:00
parent 145b07db90
commit e77e9963d6
7 changed files with 73 additions and 180 deletions

View file

@ -15,6 +15,7 @@ materials:
siz: G_IM_SIZ_4b
twoTone: true
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
gDPSetCycleType: G_CYC_2CYCLE
@ -33,21 +34,17 @@ materials:
staticLit: true
defaultVertexColor:
r: 255
g: 255
b: 255
concrete/observationwall_001a:
gDPSetTile:
filename: ../../portal_pak_modified/materials/concrete/observationwall_001a.png
siz: G_IM_SIZ_8b
fmt: G_IM_FMT_I
gDPSetCombineMode: G_CC_DECALRGB
gDPSetCombineMode: G_CC_MODULATERGB
gDPSetCycleType: G_CYC_1CYCLE
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
properties:
@ -59,9 +56,13 @@ materials:
filename: ../../portal_pak_modified/materials/metal/metalwall048b.png
siz: G_IM_SIZ_16b
gDPSetCombineMode: G_CC_DECALRGB
gDPSetCombineMode: G_CC_MODULATERGB
gDPSetCycleType: G_CYC_1CYCLE
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
properties:
tileSizeS: 0.5
tileSizeT: 0.5
@ -99,6 +100,10 @@ materials:
gDPSetCombineMode: G_CC_DECALRGB
gDPSetCycleType: G_CYC_1CYCLE
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
properties:
tileSizeS: 0.5
tileSizeT: 0.5
@ -130,7 +135,7 @@ materials:
filename: ../../portal_pak_modified/materials/metal/metalgrate018.png
siz: G_IM_SIZ_16b
gDPSetCombineMode: G_CC_DECALRGBA
gDPSetCombineMode: G_CC_MODULATERGBA
gDPSetCycleType: G_CYC_1CYCLE
gDPSetAlphaCompare: G_AC_THRESHOLD
gDPSetRenderMode: G_RM_AA_ZB_TEX_EDGE
@ -140,6 +145,10 @@ materials:
b: 255
a: 128
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
properties:
tileSizeS: 0.125
tileSizeT: 0.125
@ -215,9 +224,13 @@ materials:
filename: ../../portal_pak_modified/materials/signage/hazard_orange_03b.png
siz: G_IM_SIZ_16b
gDPSetCombineMode: G_CC_DECALRGB
gDPSetCombineMode: G_CC_MODULATERGB
gDPSetCycleType: G_CYC_1CYCLE
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
properties:
tileSizeS: 0.5
tileSizeT: 0.125
@ -228,9 +241,13 @@ materials:
filename: ../../portal_pak_modified/materials/concrete/concrete_modular_ceiling001a.png
siz: G_IM_SIZ_16b
gDPSetCombineMode: G_CC_DECALRGB
gDPSetCombineMode: G_CC_MODULATERGB
gDPSetCycleType: G_CYC_1CYCLE
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
properties:
tileSizeS: 0.5
tileSizeT: 0.5
@ -240,9 +257,13 @@ materials:
filename: ../../portal_pak_modified/materials/concrete/concrete_modular_floor001a.png
siz: G_IM_SIZ_16b
gDPSetCombineMode: G_CC_DECALRGB
gDPSetCombineMode: G_CC_MODULATERGB
gDPSetCycleType: G_CYC_1CYCLE
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
properties:
tileSizeS: 0.5
tileSizeT: 0.5
@ -379,7 +400,8 @@ materials:
g: 230
b: 230
gSPGeometryMode:
set: [G_LIGHTING, G_SHADE]
set: [G_SHADE]
clear: [G_LIGHTING]
gDPSetCombineMode:
color: ["SHADE", "0", "PRIMITIVE", "0"]
@ -575,10 +597,14 @@ materials:
t:
mirror: true
gDPSetCombineMode: G_CC_DECALRGB
gDPSetCombineMode: G_CC_MODULATERGB
gDPSetCycleType: G_CYC_1CYCLE
gDPSetTextureFilter: G_TF_BILERP
gSPGeometryMode:
set: [G_SHADE]
clear: [G_LIGHTING]
radio:
gDPSetTile:
filename: ../../portal_pak_modified/materials/models/props/radio.png

Binary file not shown.

View file

@ -190,13 +190,29 @@ class AmbientBlock:
return result
def build_ambient_blocks():
ambient_blocks = []
for obj in bpy.data.objects:
if obj.name.startswith('@ambient '):
ambient_blocks.append(AmbientBlock(obj))
for point_light in bpy.data.objects:
if point_light.type != 'LIGHT' or not point_light.name.startswith('@point_light'):
continue
pos = point_light.matrix_world @ mathutils.Vector([0, 0, 0])
distances = [block.determine_distance(pos) for block in ambient_blocks]
block_index = min_indices(distances, 1)
if len(block_index) == 0:
continue
ambient_blocks[block_index[0]].point_lights.append(point_light)
return ambient_blocks
def min_indices(elements, count):
result = []
@ -217,7 +233,7 @@ def min_indices(elements, count):
return result
def determine_vertex_color(pos, normal):
def determine_vertex_color(ambient_blocks, pos, normal):
distances = [block.determine_distance(pos) for block in ambient_blocks]
two_closest = min_indices(distances, 2)
@ -238,22 +254,14 @@ def determine_vertex_color(pos, normal):
distances[two_closest[0]] / total_weight
)
for point_light in bpy.data.objects:
if point_light.type != 'LIGHT' or not point_light.name.startswith('@point_light'):
continue
pos = point_light.matrix_world @ mathutils.Vector([0, 0, 0])
def bake_object(obj, ambient_blocks):
if obj.data.users > 1:
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.ops.object.make_single_user(obdata = True)
distances = [block.determine_distance(pos) for block in ambient_blocks]
block_index = min_indices(distances, 1)
if len(block_index) == 0:
continue
ambient_blocks[block_index[0]].point_lights.append(point_light)
def bake_object(obj):
global debug
color_layer = get_or_make_color_layer(obj.data)
@ -272,6 +280,7 @@ def bake_object(obj):
normal = rotation @ polygon.normal
vertex_color = determine_vertex_color(
ambient_blocks,
vertices[vertex_index],
normal
)
@ -284,9 +293,13 @@ def bake_object(obj):
]
def bake_scene():
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
ambient_blocks = build_ambient_blocks()
for obj in bpy.data.objects:
if should_bake_object(obj):
bake_object(obj)
bake_object(obj, ambient_blocks)
bake_scene()

View file

@ -10,7 +10,6 @@ local entities = require('tools.level_scripts.entities')
local signals = require('tools.level_scripts.signals')
local animation = require('tools.level_scripts.animation')
local dynamic_collision = require('tools.level_scripts.dynamic_collision_export')
local static_lighting = require('tools.level_scripts.static_lighting')
sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
collisionQuads = sk_definition_writer.reference_to(collision_export.collision_objects, 1),

View file

@ -5,7 +5,6 @@ local sk_mesh = require('sk_mesh')
local sk_input = require('sk_input')
local room_export = require('tools.level_scripts.room_export')
local animation = require('tools.level_scripts.animation')
local static_lighting = require('tools.level_scripts.static_lighting');
sk_definition_writer.add_header('"../build/assets/materials/static.h"')
sk_definition_writer.add_header('"levels/level_definition.h"')
@ -31,12 +30,6 @@ local function proccessStaticNodes(nodes)
original_bb.max = original_bb.max - parent_pos
end
if chunkV.material.properties.staticLit == "true" then
for index, pos in pairs(chunkV.mesh.vertices) do
chunkV.mesh.colors[1][index] = static_lighting.light_vertex(pos, chunkV.mesh.normals[index])
end
end
local gfxName = sk_mesh.generate_mesh({chunkV}, "_geo", {defaultMaterial = chunkV.material})
local mesh_bb = original_bb * bb_scale

View file

@ -1,138 +0,0 @@
local sk_scene = require('sk_scene')
local sk_math = require('sk_math');
local ambient_nodes = sk_scene.nodes_for_type('@ambient')
local ambient_blocks = {}
local function build_ambient_block(ambient_mesh)
local midpoint = sk_math.vector3(0, 0, 0)
local min = ambient_mesh.vertices[1]
local max = ambient_mesh.vertices[1]
for _, vector in pairs(ambient_mesh.vertices) do
midpoint = midpoint + vector
min = min:min(vector)
max = max:max(vector)
end
midpoint = midpoint * (1 / #ambient_mesh.vertices)
local colors = {}
for index, vector in pairs(ambient_mesh.vertices) do
local corner_index = 1
if (vector.x > midpoint.x) then
corner_index = corner_index + 1
end
if (vector.y > midpoint.y) then
corner_index = corner_index + 2
end
if (vector.z > midpoint.z) then
corner_index = corner_index + 4
end
colors[corner_index] = ambient_mesh.colors[1] and ambient_mesh.colors[1][index]
end
return {
bb = sk_math.box3(min, max),
colors = colors,
}
end
local function evaluate_ambient_block(block, pos, normal)
local lerp_values = block.bb:unlerp(pos):min(sk_math.vector3(1, 1, 1)):max(sk_math.vector3(0, 0, 0))
local x0 = block.colors[1]:lerp(block.colors[2], lerp_values.x)
local x1 = block.colors[3]:lerp(block.colors[4], lerp_values.x)
local x2 = block.colors[5]:lerp(block.colors[6], lerp_values.x)
local x3 = block.colors[7]:lerp(block.colors[8], lerp_values.x)
local y0 = x0:lerp(x1, lerp_values.y)
local y1 = x2:lerp(x3, lerp_values.y)
return y0:lerp(y1, lerp_values.z)
end
for index, ambient_node in pairs(ambient_nodes) do
for _, mesh in pairs(ambient_node.node.meshes) do
local global_mesh = mesh:transform(ambient_node.node.full_transformation)
table.insert(ambient_blocks, build_ambient_block(global_mesh))
end
end
local function find_nearest_ambient_boxes(pos, max_count)
local boxes = {};
local distances = {};
for _, ambient_block in pairs(ambient_blocks) do
local distance = ambient_block.bb:distance_to_point(pos)
-- if inside a block just return it
if distance <= 0 then
return {ambient_block}, {1}
end
local insert_index = #boxes + 1
for index, other_distance in pairs(distances) do
if distance < other_distance then
insert_index = index
end
end
if insert_index < max_count then
table.insert(boxes, insert_index, ambient_block)
table.insert(distances, insert_index, distance)
if #boxes > max_count then
table.remove(boxes)
table.remove(distances)
end
end
end
if #distances == 1 then
return boxes, {1}
end
local weights = {}
local total_weight = 0
for index, distance in pairs(distances) do
total_weight = total_weight + distance
weights[index] = distance
end
for index, _ in pairs(weights) do
weights[index] = 1 - weights[index] / total_weight
end
return boxes, weights
end
local function light_vertex(pos, normal)
local boxes, weights = find_nearest_ambient_boxes(pos, 2)
if #boxes == 0 then
return sk_math.color4(1, 1, 1, 1)
end
local result = sk_math.color4(0, 0, 0, 0)
for index, block in pairs(boxes) do
result = result + evaluate_ambient_block(block, pos, normal) * weights[index]
end
return result
end
return {
light_vertex = light_vertex,
}