collada_scene: materials, lighting, textures

This commit is contained in:
Zack Buhman 2026-02-24 04:47:03 +00:00
parent 6534e64957
commit bef01af5e8
8 changed files with 801 additions and 168 deletions

View File

@ -12,7 +12,13 @@ local pixel_data = love.filesystem.newFileData("pixel.glsl")
local vertex_data = love.filesystem.newFileData("vertex.glsl") local vertex_data = love.filesystem.newFileData("vertex.glsl")
local shader = love.graphics.newShader(pixel_data, vertex_data) local shader = love.graphics.newShader(pixel_data, vertex_data)
function load_geometries(vertex_buffer, index_buffer, geometries) local images_textures = {}
local node_instances = {}
local collada_scene
collada_scene = {
load_geometries = function(vertex_buffer, index_buffer, geometries)
for _, geometry in ipairs(geometries) do for _, geometry in ipairs(geometries) do
local offset = geometry.mesh.vertex_buffer_offset / (4 * 3 * 3) local offset = geometry.mesh.vertex_buffer_offset / (4 * 3 * 3)
local attribute_list = pnt_attribute_list(vertex_buffer, offset) local attribute_list = pnt_attribute_list(vertex_buffer, offset)
@ -23,11 +29,22 @@ function load_geometries(vertex_buffer, index_buffer, geometries)
geometries_meshes[geometry] = mesh geometries_meshes[geometry] = mesh
end end
end end,
local node_instances = {} load_images = function(base_path, images)
local image_index = 0
for _, image in ipairs(images) do
assert(string.sub(image.uri, 1, 1) == ".")
path = base_path .. string.sub(image.uri, 2)
print("load image", path)
local image_data = love.image.newImageData(path)
local texture = love.graphics.newTexture(image_data)
images_textures[image_index] = texture
image_index = image_index + 1
end
end,
function node_world_transform(node) node_world_transform = function(node)
local world local world
if node.parent_index >= 0 then if node.parent_index >= 0 then
world = node_instances[node.parent_index].world world = node_instances[node.parent_index].world
@ -57,61 +74,68 @@ function node_world_transform(node)
world = m * world world = m * world
end end
return world return world
end end,
function load_node_world_transforms(nodes) load_node_world_transforms = function(nodes)
local node_index = 0 local node_index = 0
for _, node in ipairs(nodes) do for _, node in ipairs(nodes) do
world = node_world_transform(node) world = collada_scene.node_world_transform(node)
node_instances[node_index] = { world = world } node_instances[node_index] = { world = world }
node_index = node_index + 1 node_index = node_index + 1
end end
end end,
function set_color_or_texture(color_or_texture, color_uniform, sampler_uniform) set_color_or_texture = function(color_or_texture, color_uniform, sampler_uniform)
if color_or_texture.type == collada_types.color_or_texture_type.COLOR then if color_or_texture.type == collada_types.color_or_texture_type.COLOR then
shader:send(color_uniform, color_or_texture.color) shader:send(color_uniform, color_or_texture.color)
elseif color_or_texture.type == collada_types.color_or_texture_type.TEXTURE then elseif color_or_texture.type == collada_types.color_or_texture_type.TEXTURE then
assert(false) shader:send(sampler_uniform, images_textures[color_or_texture.texture.image_index])
--shader:send(sampler_uniform, )
else else
assert(false) assert(false)
end end
end end,
function set_instance_material(instance_material) set_instance_material = function(instance_material)
effect = instance_material.material.effect local effect = instance_material.material.effect
if effect.type == collada_types.effect_type.BLINN then if effect.type == collada_types.effect_type.BLINN then
set_color_or_texture(effect.blinn.emission, "emission_color", "emission_sampler"); collada_scene.set_color_or_texture(effect.blinn.emission, "emission_color", "emission_sampler");
set_color_or_texture(effect.blinn.ambient, "ambient_color", "ambient_sampler"); collada_scene.set_color_or_texture(effect.blinn.ambient, "ambient_color", "ambient_sampler");
set_color_or_texture(effect.blinn.diffuse, "diffuse_color", "diffuse_sampler"); collada_scene.set_color_or_texture(effect.blinn.diffuse, "diffuse_color", "diffuse_sampler");
set_color_or_texture(effect.blinn.specular, "specular_color", "specular_sampler"); collada_scene.set_color_or_texture(effect.blinn.specular, "specular_color", "specular_sampler");
shader:send("shininess", effect.blinn.shininess); shader:send("shininess", effect.blinn.shininess);
elseif effect.type == collada_types.effect_type.LAMBERT then elseif effect.type == collada_types.effect_type.LAMBERT then
set_color_or_texture(effect.lambert.emission, "emission_color", "emission_sampler"); collada_scene.set_color_or_texture(effect.lambert.emission, "emission_color", "emission_sampler");
set_color_or_texture(effect.lambert.ambient, "ambient_color", "ambient_sampler"); collada_scene.set_color_or_texture(effect.lambert.ambient, "ambient_color", "ambient_sampler");
set_color_or_texture(effect.lambert.diffuse, "diffuse_color", "diffuse_sampler"); collada_scene.set_color_or_texture(effect.lambert.diffuse, "diffuse_color", "diffuse_sampler");
elseif effect.type == collada_types.effect_type.PHONG then elseif effect.type == collada_types.effect_type.PHONG then
set_color_or_texture(effect.phong.emission, "emission_color", "emission_sampler"); collada_scene.set_color_or_texture(effect.phong.emission, "emission_color", "emission_sampler");
set_color_or_texture(effect.phong.ambient, "ambient_color", "ambient_sampler"); collada_scene.set_color_or_texture(effect.phong.ambient, "ambient_color", "ambient_sampler");
set_color_or_texture(effect.phong.diffuse, "diffuse_color", "diffuse_sampler"); collada_scene.set_color_or_texture(effect.phong.diffuse, "diffuse_color", "diffuse_sampler");
set_color_or_texture(effect.phong.specular, "specular_color", "specular_sampler"); collada_scene.set_color_or_texture(effect.phong.specular, "specular_color", "specular_sampler");
shader:send("shininess", effect.phong.shininess); shader:send("shininess", effect.phong.shininess);
elseif effect.type == collada_types.effect_type.CONSTANT then elseif effect.type == collada_types.effect_type.CONSTANT then
shader:send("emission_color", effect.constant.color) shader:send("emission_color", effect.constant.color)
else else
assert(false) assert(false)
end end
end
function draw_geometry(geometry, instance_materials) local texture_channel = {
instance_material.emission.input_set,
instance_material.ambient.input_set,
instance_material.diffuse.input_set,
instance_material.specular.input_set,
}
shader:send("texture_channel", texture_channel)
end,
draw_geometry = function(geometry, instance_materials)
local base_index_buffer_offset = geometry.mesh.index_buffer_offset / 4 local base_index_buffer_offset = geometry.mesh.index_buffer_offset / 4
local mesh = geometries_meshes[geometry] local mesh = geometries_meshes[geometry]
for _, instance_material in ipairs(instance_materials) do for _, instance_material in ipairs(instance_materials) do
set_instance_material(instance_material) collada_scene.set_instance_material(instance_material)
local triangles = geometry.mesh.triangles[instance_material.element_index + 1] local triangles = geometry.mesh.triangles[instance_material.element_index + 1]
local index_offset = base_index_buffer_offset + triangles.index_offset local index_offset = base_index_buffer_offset + triangles.index_offset
@ -119,9 +143,9 @@ function draw_geometry(geometry, instance_materials)
mesh:setDrawRange(1 + index_offset, index_count) mesh:setDrawRange(1 + index_offset, index_count)
love.graphics.draw(mesh, 0, 0, 0, 0, 0) love.graphics.draw(mesh, 0, 0, 0, 0, 0)
end end
end end,
function draw_node(node_index, node, transform) draw_node = function(node_index, node, transform)
if node.type ~= collada_types.node_type.NODE then if node.type ~= collada_types.node_type.NODE then
return return
end end
@ -136,22 +160,26 @@ function draw_node(node_index, node, transform)
shader:send("transform", "column", transform.data) shader:send("transform", "column", transform.data)
for _, instance_geometry in ipairs(node.instance_geometries) do for _, instance_geometry in ipairs(node.instance_geometries) do
draw_geometry(instance_geometry.geometry, instance_geometry.instance_materials) collada_scene.draw_geometry(instance_geometry.geometry, instance_geometry.instance_materials)
end end
end end,
function draw_nodes(nodes, transform) draw_nodes = function(nodes, transform)
love.graphics.setShader(shader) love.graphics.setShader(shader)
shader:send("view_position", {-88.57101, -71.71298, 104.5738, 1.0}) shader:send("view_position", {-88.57101, -71.71298, 104.5738, 1.0})
shader:send("light_position", {0.0, -56.804, 58.237, 1.0}) shader:send("light_position", {0.0, -56.804, 58.237, 1.0})
local node_index = 0 local node_index = 0
for _, node in ipairs(nodes) do for _, node in ipairs(nodes) do
draw_node(node_index, node, transform) collada_scene.draw_node(node_index, node, transform)
node_index = node_index + 1 node_index = node_index + 1
end end
end end,
}
return { return {
draw_nodes = draw_nodes draw_nodes = collada_scene.draw_nodes,
load_geometries = collada_scene.load_geometries,
load_node_world_transforms = collada_scene.load_node_world_transforms,
load_images = collada_scene.load_images,
} }

View File

@ -54,11 +54,9 @@ function love.load(args)
local vertex_buffer = love.graphics.newBuffer(vertexformat, vertex_data, { vertex = true, usage = "static" }) local vertex_buffer = love.graphics.newBuffer(vertexformat, vertex_data, { vertex = true, usage = "static" })
local index_buffer = love.graphics.newBuffer("uint32", index_data, { index = true, usage = "static" }) local index_buffer = love.graphics.newBuffer("uint32", index_data, { index = true, usage = "static" })
load_geometries(vertex_buffer, index_buffer, scene_test.descriptor.geometries) collada_scene.load_geometries(vertex_buffer, index_buffer, scene_test.descriptor.geometries)
load_node_world_transforms(scene_test.descriptor.nodes) collada_scene.load_node_world_transforms(scene_test.descriptor.nodes)
collada_scene.load_images("scene/test", scene_test.descriptor.images)
local image_data = love.image.newCompressedData('bird.dds')
texture = love.graphics.newTexture(image_data)
end end
local rotation = 0.0 local rotation = 0.0
@ -90,5 +88,5 @@ function love.draw()
local transform = view * projection local transform = view * projection
love.graphics.setDepthMode("less", true) love.graphics.setDepthMode("less", true)
draw_nodes(scene_test.descriptor.nodes, transform) collada_scene.draw_nodes(scene_test.descriptor.nodes, transform)
end end

View File

@ -10,35 +10,56 @@ uniform vec4 diffuse_color;
uniform vec4 specular_color; uniform vec4 specular_color;
uniform float shininess; uniform float shininess;
uniform sampler2D emission_sampler;
uniform sampler2D ambient_sampler;
uniform sampler2D diffuse_sampler;
uniform sampler2D specular_sampler;
uniform vec4 view_position; uniform vec4 view_position;
uniform vec4 light_position; uniform vec4 light_position;
//uniform int4 texture_channel; uniform ivec4 texture_channel;
uniform sampler2D texture_sampler;
out vec4 out_color; out vec4 out_color;
void pixelmain() void pixelmain()
{ {
//vec4 texColor = texture(texture_sampler, PixelTexture.xy);
vec3 normal = normalize(PixelNormal.xyz); vec3 normal = normalize(PixelNormal.xyz);
vec3 view_direction = normalize(view_position.xyz - PixelWorldPosition.xyz); vec3 view_direction = normalize(view_position.xyz - PixelWorldPosition.xyz);
vec3 light_direction = normalize(light_position.xyz - PixelWorldPosition.xyz); vec3 light_direction = normalize(light_position.xyz - PixelWorldPosition.xyz);
vec3 reflect_light_direction = reflect(-light_direction, normal); vec3 reflect_light_direction = reflect(-light_direction, normal);
vec3 emission = emission_color.xyz; vec4 emission;
vec3 ambient = ambient_color.xyz; vec4 ambient;
vec3 diffuse = diffuse_color.xyz; vec4 diffuse;
vec3 specular = specular_color.xyz; vec4 specular;
if (texture_channel.x >= 0) { // emission
emission = texture(emission_sampler, PixelTexture.xy);
} else {
emission = emission_color;
}
if (texture_channel.y >= 0) { // ambient
ambient = texture(ambient_sampler, PixelTexture.xy);
} else {
ambient = ambient_color;
}
if (texture_channel.z >= 0) { // diffuse
diffuse = texture(diffuse_sampler, PixelTexture.xy);
} else {
diffuse = diffuse_color;
}
if (texture_channel.w >= 0) { // specular
specular = texture(specular_sampler, PixelTexture.xy);
} else {
specular = specular_color;
}
float diffuse_intensity = max(dot(normal, light_direction), 0.0); float diffuse_intensity = max(dot(normal, light_direction), 0.0);
float specular_intensity = pow(max(dot(view_direction, reflect_light_direction), 0.0), shininess); float specular_intensity = pow(max(dot(view_direction, reflect_light_direction), 0.0), shininess);
vec3 color = emission * 0; vec3 color = emission.xyz * 0;
color += ambient * 0; color += ambient.xyz * 0;
color += diffuse * diffuse_intensity; color += diffuse.xyz * diffuse_intensity;
color += specular * specular_intensity * 0.3; color += specular.xyz * specular_intensity * 0.3;
out_color = vec4(color, 1.0); out_color = vec4(color, 1.0);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

528
scene/test/test.DAE Normal file

File diff suppressed because one or more lines are too long

View File

@ -11,28 +11,37 @@ local light_environmentambientlight = {
type = collada_types.light_type.AMBIENT, type = collada_types.light_type.AMBIENT,
color = {0.0, 0.0, 0.0}, color = {0.0, 0.0, 0.0},
} }
local images = { local light_omni001_light = {
type = collada_types.light_type.POINT,
color = {1.0, 1.0, 1.0},
} }
local effect_coloreffectr228g184b153 = { -- logOnly_png
type = collada_types.effect_type.PHONG, local image_logonly_png = {
phong = { uri = "./images/0_logOnly.png",
}
local images = {
image_logonly_png,
}
local effect_material__47 = {
type = collada_types.effect_type.BLINN,
blinn = {
emission = { emission = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {0.0, 0.0, 0.0, 0.0}, color = {0.0, 0.0, 0.0, 1.0},
}, },
ambient = { ambient = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {0.8941176, 0.7215686, 0.6, 1.0}, color = {0.588, 0.588, 0.588, 1.0},
}, },
diffuse = { diffuse = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.TEXTURE,
color = {0.8941176, 0.7215686, 0.6, 1.0}, texture = { image_index = 0 }, -- logOnly_png
}, },
specular = { specular = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {1.0, 1.0, 1.0, 1.0}, color = {0.36, 0.36, 0.36, 1.0},
}, },
shininess = 10.0, shininess = 37.0,
reflective = { reflective = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {0.0, 0.0, 0.0, 1.0}, color = {0.0, 0.0, 0.0, 1.0},
@ -79,26 +88,26 @@ local effect_coloreffectr153g228b184 = {
index_of_refraction = 0.0, index_of_refraction = 0.0,
} }
} }
local effect_coloreffectr177g26b88 = { local effect_material__46 = {
type = collada_types.effect_type.PHONG, type = collada_types.effect_type.BLINN,
phong = { blinn = {
emission = { emission = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {0.0, 0.0, 0.0, 0.0}, color = {0.0, 0.0, 0.0, 1.0},
}, },
ambient = { ambient = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {0.6941176, 0.1019608, 0.345098, 1.0}, color = {0.6941177, 0.1921569, 0.4039216, 1.0},
}, },
diffuse = { diffuse = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {0.6941176, 0.1019608, 0.345098, 1.0}, color = {0.6941177, 0.1921569, 0.4039216, 1.0},
}, },
specular = { specular = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {1.0, 1.0, 1.0, 1.0}, color = {0.27, 0.27, 0.27, 1.0},
}, },
shininess = 10.0, shininess = 38.0,
reflective = { reflective = {
type = collada_types.color_or_texture_type.COLOR, type = collada_types.color_or_texture_type.COLOR,
color = {0.0, 0.0, 0.0, 1.0}, color = {0.0, 0.0, 0.0, 1.0},
@ -145,18 +154,18 @@ local effect_coloreffectr5g54b179 = {
index_of_refraction = 0.0, index_of_refraction = 0.0,
} }
} }
local material_coloreffectr228g184b153_material = {
effect = effect_coloreffectr228g184b153,
}
local material_coloreffectr153g228b184_material = { local material_coloreffectr153g228b184_material = {
effect = effect_coloreffectr153g228b184, effect = effect_coloreffectr153g228b184,
} }
local material_coloreffectr177g26b88_material = {
effect = effect_coloreffectr177g26b88,
}
local material_coloreffectr5g54b179_material = { local material_coloreffectr5g54b179_material = {
effect = effect_coloreffectr5g54b179, effect = effect_coloreffectr5g54b179,
} }
local material_material__47_material = {
effect = effect_material__47,
}
local material_material__46_material = {
effect = effect_material__46,
}
local input_elements_position_0_3_normal_0_3_texcoord_0_3 = { local input_elements_position_0_3_normal_0_3_texcoord_0_3 = {
{ {
semantic = "POSITION", semantic = "POSITION",
@ -274,11 +283,11 @@ local transforms_node_plane = {
local instance_geometry_instance_materials_node_plane_0 = { local instance_geometry_instance_materials_node_plane_0 = {
{ {
element_index = 0, -- an index into mesh.triangles element_index = 0, -- an index into mesh.triangles
material = material_coloreffectr228g184b153_material, material = material_material__47_material,
emission = { input_set = -1 }, emission = { input_set = -1 },
ambient = { input_set = -1 }, ambient = { input_set = -1 },
diffuse = { input_set = -1 }, diffuse = { input_set = 0 },
specular = { input_set = -1 }, specular = { input_set = -1 },
}, },
} }
@ -400,7 +409,7 @@ local transforms_node_torusknot25 = {
local instance_geometry_instance_materials_node_torusknot25_0 = { local instance_geometry_instance_materials_node_torusknot25_0 = {
{ {
element_index = 0, -- an index into mesh.triangles element_index = 0, -- an index into mesh.triangles
material = material_coloreffectr177g26b88_material, material = material_material__46_material,
emission = { input_set = -1 }, emission = { input_set = -1 },
ambient = { input_set = -1 }, ambient = { input_set = -1 },
@ -574,6 +583,47 @@ local node_node_camera_target = {
channels = node_channels_node_camera_target, channels = node_channels_node_camera_target,
channels_count = 0, channels_count = 0,
} }
local transforms_node_omni001 = {
{
type = collada_types.transform_type.TRANSLATE,
translate = {-2.48297e-06, -56.80384, 58.23672},
},
{
type = collada_types.transform_type.ROTATE,
rotate = {-0.5773502, 0.5773503, 0.5773503, -120.0},
},
}
local instance_geometries_node_omni001 = {
}
local instance_controllers_node_omni001 = {
}
local instance_lights_node_omni001 = {
{
light = light_omni001_light,
}
}
local node_channels_node_omni001 = {
}
local node_node_omni001 = {
parent_index = -1,
type = collada_types.node_type.NODE,
transforms = transforms_node_omni001,
transforms_count = 2,
instance_geometries = instance_geometries_node_omni001,
instance_geometries_count = 0,
instance_controllers = instance_controllers_node_omni001,
instance_controllers_count = 0,
instance_lights = instance_lights_node_omni001,
instance_lights_count = 1,
channels = node_channels_node_omni001,
channels_count = 0,
}
local nodes = { local nodes = {
node_node_environmentambientlight, -- 0 node_node_environmentambientlight, -- 0
node_node_plane, -- 1 node_node_plane, -- 1
@ -583,6 +633,7 @@ local nodes = {
node_node_camera, -- 5 node_node_camera, -- 5
node_node_cameratargethelper, -- 6 node_node_cameratargethelper, -- 6
node_node_camera_target, -- 7 node_node_camera_target, -- 7
node_node_omni001, -- 8
} }
local inputs_list = { local inputs_list = {
{ {

View File

@ -0,0 +1,6 @@
IMAGES += image/0_logOnly.DDS
image/0_logOnly.DDS: ./images/0_logOnly.png
@mkdir -p image
texconv10.exe -f BC1_UNORM -nologo "$<"
mv "$(<:.png=.DDS)" "$@"

View File

@ -2,3 +2,4 @@ RES_SCENES_TEST_VTX RCDATA "test.vtx"
RES_SCENES_TEST_VJW RCDATA "test.vjw" RES_SCENES_TEST_VJW RCDATA "test.vjw"
RES_SCENES_TEST_IDX RCDATA "test.idx" RES_SCENES_TEST_IDX RCDATA "test.idx"
_0_LOGONLY_PNG RCDATA "image/0_logOnly.DDS"