collada_scene: shadow mapping

This commit is contained in:
Zack Buhman 2026-02-27 03:07:26 +00:00
parent 8f22a0faf2
commit ba777fbf3c
10 changed files with 2004 additions and 160 deletions

View File

@ -6,12 +6,28 @@ local scalar = _math.scalar
local collada_types = require 'collada_types' local collada_types = require 'collada_types'
local pixel_data = love.filesystem.newFileData("pixel.glsl") local pixel_color_data = love.filesystem.newFileData("pixel_color.glsl")
local pixel_shadow_data = love.filesystem.newFileData("pixel_shadow.glsl")
local vertex_static_data = love.filesystem.newFileData("vertex_static.glsl") local vertex_static_data = love.filesystem.newFileData("vertex_static.glsl")
local vertex_skinned_data = love.filesystem.newFileData("vertex_skinned.glsl") local vertex_skinned_data = love.filesystem.newFileData("vertex_skinned.glsl")
local shader_static = love.graphics.newShader(pixel_data, vertex_static_data) local shader_color_static = love.graphics.newShader(pixel_color_data, vertex_static_data)
local shader_skinned = love.graphics.newShader(pixel_data, vertex_skinned_data) local shader_color_skinned = love.graphics.newShader(pixel_color_data, vertex_skinned_data)
local shader_shadow_static = love.graphics.newShader(pixel_shadow_data, vertex_static_data)
local shader_shadow_skinned = love.graphics.newShader(pixel_shadow_data, vertex_skinned_data)
local shader_set = {
shadow = {
static = shader_shadow_static,
skinned = shader_shadow_skinned,
},
color = {
static = shader_color_static,
skinned = shader_color_skinned,
},
}
local send_material
local current_shader_set
local current_shader local current_shader
local images_textures = {} local images_textures = {}
@ -46,13 +62,16 @@ collada_scene = {
{ name = 'Joint', format = 'int32vec4' }, { name = 'Joint', format = 'int32vec4' },
{ name = 'Weight', format = 'floatvec4' }, { name = 'Weight', format = 'floatvec4' },
} }
shader_static:send("VertexPNTLayout", vtx_shaderstorage_buffer) shader_color_static:send("VertexPNTLayout", vtx_shaderstorage_buffer)
shader_skinned:send("VertexPNTLayout", vtx_shaderstorage_buffer) shader_color_skinned:send("VertexPNTLayout", vtx_shaderstorage_buffer)
shader_shadow_static:send("VertexPNTLayout", vtx_shaderstorage_buffer)
shader_shadow_skinned:send("VertexPNTLayout", vtx_shaderstorage_buffer)
local vjw_data = love.filesystem.newFileData(vjw_path) local vjw_data = love.filesystem.newFileData(vjw_path)
if vjw_data:getSize() ~= 0 then if vjw_data:getSize() ~= 0 then
local vjw_shaderstorage_buffer = love.graphics.newBuffer(vjw_format, vjw_data, { shaderstorage = true, usage = "static" }) local vjw_shaderstorage_buffer = love.graphics.newBuffer(vjw_format, vjw_data, { shaderstorage = true, usage = "static" })
shader_skinned:send("VertexJWLayout", vjw_shaderstorage_buffer) shader_color_skinned:send("VertexJWLayout", vjw_shaderstorage_buffer)
shader_shadow_skinned:send("VertexJWLayout", vjw_shaderstorage_buffer)
end end
end, end,
@ -118,7 +137,9 @@ collada_scene = {
local base_index_buffer_offset = mesh.index_buffer_offset / 4 local base_index_buffer_offset = mesh.index_buffer_offset / 4
for _, instance_material in ipairs(instance_materials) do for _, instance_material in ipairs(instance_materials) do
if send_material then
collada_scene.set_instance_material(instance_material) collada_scene.set_instance_material(instance_material)
end
local triangles = mesh.triangles[instance_material.element_index + 1] local triangles = 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
@ -184,7 +205,7 @@ collada_scene = {
end end
end, end,
draw_node = function(view_position, light_position, node_state, node, node_instance, transform) draw_node = function(node_state, transform, light_transform, node, node_instance)
if node.type ~= collada_types.node_type.NODE then if node.type ~= collada_types.node_type.NODE then
return return
end end
@ -195,31 +216,37 @@ collada_scene = {
local world = node_instance.world local world = node_instance.world
transform = world * transform transform = world * transform
light_transform = world * light_transform
if node.instance_geometries_count > 0 then if node.instance_geometries_count > 0 then
current_shader = shader_static current_shader = current_shader_set.static
love.graphics.setShader(current_shader) love.graphics.setShader(current_shader)
current_shader:send("view_position", view_position.data)
current_shader:send("light_position", light_position.data)
current_shader:send("world_transform", "column", world.data) current_shader:send("world_transform", "column", world.data)
current_shader:send("light_transform", "column", light_transform.data)
current_shader:send("transform", "column", transform.data) current_shader:send("transform", "column", transform.data)
collada_scene.draw_instance_geometries(node.instance_geometries) collada_scene.draw_instance_geometries(node.instance_geometries)
end end
if node.instance_controllers_count > 0 then if node.instance_controllers_count > 0 then
current_shader = shader_skinned current_shader = current_shader_set.skinned
love.graphics.setShader(current_shader) love.graphics.setShader(current_shader)
current_shader:send("view_position", view_position)
current_shader:send("light_position", light_position)
current_shader:send("world_transform", "column", world.data) current_shader:send("world_transform", "column", world.data)
current_shader:send("light_transform", "column", light_transform.data)
current_shader:send("transform", "column", transform.data) current_shader:send("transform", "column", transform.data)
collada_scene.draw_instance_controllers(node_state, node.instance_controllers) collada_scene.draw_instance_controllers(node_state, node.instance_controllers)
end end
end, end,
draw_nodes = function(node_state, projection) draw_nodes = function(node_state, transform, light_transform)
local node_index = 0
for _, node in ipairs(node_state.nodes) do
local node_instance = node_state.node_instances[node_index]
collada_scene.draw_node(node_state, transform, light_transform, node, node_instance)
node_index = node_index + 1
end
end,
draw_scene = function(node_state, perspective_projection, orthographic_projection)
local camera_world = node_state.node_instances[node_state.camera].world local camera_world = node_state.node_instances[node_state.camera].world
local view_position = vec3.transform(vec3._zero, camera_world) local view_position = vec3.transform(vec3._zero, camera_world)
@ -229,23 +256,47 @@ collada_scene = {
local light_world = node_state.node_instances[node_state.light].world local light_world = node_state.node_instances[node_state.light].world
local light_position = vec3.transform(vec3._zero, light_world) local light_position = vec3.transform(vec3._zero, light_world)
local view = mat4.look_at_rh(view_position, local up = vec3(0, 0, 1)
view_target_position,
vec3(0, 0, 1))
local transform = view * projection local view = mat4.look_at_rh(view_position, view_target_position, up)
local transform = view * perspective_projection
local node_index = 0 local light_view = mat4.look_at_rh(light_position, vec3._zero, up)
for _, node in ipairs(node_state.nodes) do local light_transform = light_view * orthographic_projection
local node_instance = node_state.node_instances[node_index]
collada_scene.draw_node(view_position, light_position, node_state, node, node_instance, transform) ----------------------------------------------------------------------
node_index = node_index + 1 -- shadow
end ----------------------------------------------------------------------
love.graphics.setCanvas({g_shadow_canvas, depth=true})
love.graphics.clear({0.0, 0.0, 0.0, 1.0})
current_shader_set = shader_set.shadow
send_material = false
collada_scene.draw_nodes(node_state, light_transform, light_transform)
----------------------------------------------------------------------
-- color
----------------------------------------------------------------------
shader_color_static:send("view_position", view_position.data)
shader_color_static:send("light_position", light_position.data)
shader_color_static:send("shadow_sampler", g_shadow_canvas)
shader_color_skinned:send("view_position", view_position.data)
shader_color_skinned:send("light_position", light_position.data)
shader_color_skinned:send("shadow_sampler", g_shadow_canvas)
love.graphics.setCanvas()
love.graphics.clear({0.0, 0.0, 0.0, 1.0})
current_shader_set = shader_set.color
send_material = true
collada_scene.draw_nodes(node_state, transform, light_transform)
end, end,
} }
return { return {
draw_nodes = collada_scene.draw_nodes, draw_nodes = collada_scene.draw_nodes,
draw_scene = collada_scene.draw_scene,
load_buffers = collada_scene.load_buffers, load_buffers = collada_scene.load_buffers,
load_node_instances = collada_scene.load_node_instances, load_node_instances = collada_scene.load_node_instances,
load_images = collada_scene.load_images, load_images = collada_scene.load_images,

View File

@ -35,9 +35,6 @@ local scenes = {
local node_state local node_state
local g_position_canvas
local g_normal_canvas
local screen_index_buffer local screen_index_buffer
local screen_shader local screen_shader
@ -57,8 +54,8 @@ end
local load_screen_shader = function() local load_screen_shader = function()
load_screen_index_buffer() load_screen_index_buffer()
local pixel_data = love.filesystem.newFileData("pixel_sobel.glsl") local pixel_data = love.filesystem.newFileData("pixel_screen.glsl")
local vertex_data = love.filesystem.newFileData("vertex_sobel.glsl") local vertex_data = love.filesystem.newFileData("vertex_screen.glsl")
screen_shader = love.graphics.newShader(pixel_data, vertex_data) screen_shader = love.graphics.newShader(pixel_data, vertex_data)
end end
@ -80,6 +77,8 @@ function love.load(args)
g_normal_canvas = love.graphics.newCanvas(1024, 1024, {format = "rgba32f"}) g_normal_canvas = love.graphics.newCanvas(1024, 1024, {format = "rgba32f"})
g_color_canvas = love.graphics.newCanvas(1024, 1024, {format = "rgba32f"}) g_color_canvas = love.graphics.newCanvas(1024, 1024, {format = "rgba32f"})
g_shadow_canvas = love.graphics.newCanvas(2048, 2048, {format = "r32f"})
load_screen_shader() load_screen_shader()
end end
@ -93,26 +92,24 @@ function love.draw()
width, height = love.graphics.getDimensions() width, height = love.graphics.getDimensions()
local aspect_ratio = width / height local aspect_ratio = width / height
local projection = mat4.perspective_fov_rh(scalar.convert_to_radians(45 * 0.5), local perspective_projection = mat4.perspective_fov_rh(scalar.convert_to_radians(45 * 0.5),
aspect_ratio, aspect_ratio,
0.1, 0.1,
10000.0) 10000.0)
--projection = mat4.orthographic_rh(500, 500, 0.1, 10000.0) local orthographic_projection = mat4.orthographic_rh(300, 300, 200, 400.0)
local world1 = mat4.rotation_z(rotation) local world1 = mat4.rotation_z(rotation)
local world2 = mat4.rotation_z(rotation * 0.5) local world2 = mat4.rotation_z(rotation * 0.5)
--local world3 = mat4.translation(0, 0, -0.5) --local world3 = mat4.translation(0, 0, -0.5)
rotation = rotation + 0.01 rotation = rotation + 0.01
local transform = projection
collada_scene_animate.update(t, node_state) collada_scene_animate.update(t, node_state)
t = t + 0.016 t = t + 0.016 * 0.1
love.graphics.setBlendMode("replace", "premultiplied") love.graphics.setBlendMode("replace", "premultiplied")
love.graphics.setDepthMode("less", true) love.graphics.setDepthMode("less", true)
collada_scene.draw_nodes(node_state, transform) collada_scene.draw_scene(node_state, perspective_projection, orthographic_projection)
-- love.graphics.setCanvas({ -- love.graphics.setCanvas({
-- g_color_canvas, -- g_color_canvas,
@ -128,7 +125,6 @@ function love.draw()
-- love.graphics.setCanvas() -- love.graphics.setCanvas()
-- love.graphics.setShader(screen_shader) -- love.graphics.setShader(screen_shader)
--screen_shader:send("g_normal_sampler", g_normal_canvas) -- screen_shader:send("g_sampler", g_shadow_canvas)
--screen_shader:send("g_color_sampler", g_color_canvas)
-- love.graphics.drawFromShader(screen_index_buffer, 3 * 2, 1, 1) -- love.graphics.drawFromShader(screen_index_buffer, 3 * 2, 1, 1)
end end

View File

@ -3,6 +3,7 @@
varying vec4 PixelNormal; varying vec4 PixelNormal;
varying vec4 PixelTexture; varying vec4 PixelTexture;
varying vec4 PixelWorldPosition; varying vec4 PixelWorldPosition;
varying vec4 PixelLightPosition;
uniform vec4 emission_color; uniform vec4 emission_color;
uniform vec4 ambient_color; uniform vec4 ambient_color;
@ -15,6 +16,8 @@ uniform sampler2D ambient_sampler;
uniform sampler2D diffuse_sampler; uniform sampler2D diffuse_sampler;
uniform sampler2D specular_sampler; uniform sampler2D specular_sampler;
uniform sampler2D shadow_sampler;
uniform vec4 view_position; uniform vec4 view_position;
uniform vec4 light_position; uniform vec4 light_position;
uniform ivec4 texture_channel; uniform ivec4 texture_channel;
@ -23,6 +26,18 @@ layout (location = 0) out vec4 g_color;
layout (location = 1) out vec4 g_position; layout (location = 1) out vec4 g_position;
layout (location = 2) out vec4 g_normal; layout (location = 2) out vec4 g_normal;
float Shadow(vec3 normal, vec3 light_direction)
{
vec3 projected = PixelLightPosition.xyz / PixelLightPosition.w;
projected = projected * vec3(0.5, -0.5, 0.5) + 0.5;
float shadow_depth = texture(shadow_sampler, projected.xy).x;
float fragment_depth = projected.z;
float bias = max(0.05 * (1.0 - dot(normal, light_direction)), 0.005);
return fragment_depth - bias > shadow_depth ? 0.3 : 1.0;
//return shadow_depth;
}
void pixelmain() void pixelmain()
{ {
vec3 normal = normalize(PixelNormal.xyz); vec3 normal = normalize(PixelNormal.xyz);
@ -63,7 +78,11 @@ void pixelmain()
color += diffuse.xyz * diffuse_intensity; color += diffuse.xyz * diffuse_intensity;
color += specular.xyz * specular_intensity * 0.3; color += specular.xyz * specular_intensity * 0.3;
g_position = vec4(PixelWorldPosition.xyz * 0.0005 + 0.5, 0.0); color *= Shadow(normal, light_direction);
g_normal = vec4(normal * 0.5 + 0.5, PixelWorldPosition.z * 0.001 + 0.5);
g_color = vec4(color, 1.0); g_color = vec4(color, 1.0);
//float s = Shadow();
//g_color = vec4(s, s, s, 1.0);
g_position = vec4(PixelWorldPosition.xyz, 1.0);
g_normal = vec4(normal, 0.0);
} }

12
pixel_screen.glsl Normal file
View File

@ -0,0 +1,12 @@
#pragma language glsl3
uniform sampler2D g_sampler;
out vec4 out_color;
void pixelmain()
{
vec4 color = texelFetch(g_sampler, ivec2(gl_FragCoord), 0);
out_color = vec4(color.xyz, 1.0);
}

8
pixel_shadow.glsl Normal file
View File

@ -0,0 +1,8 @@
#pragma language glsl3
layout (location = 0) out float g_out;
void pixelmain()
{
g_out = gl_FragCoord.z;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

17
vertex_screen.glsl Normal file
View File

@ -0,0 +1,17 @@
#pragma language glsl3
const vec4 vtx[4] = vec4[](vec4(-1.0, 1.0, 0.0, 1.0), // tl
vec4( 1.0, 1.0, 0.0, 1.0), // tr
vec4( 1.0, -1.0, 0.0, 1.0), // br
vec4(-1.0, -1.0, 0.0, 1.0)); // bl
varying vec4 PixelTexture;
void vertexmain()
{
vec4 vertex = vtx[gl_VertexID];
PixelTexture = vec4(vertex.xy * vec2(0.5, -0.5) + 0.5, 0, 0);
love_Position = vertex;
}

View File

@ -26,12 +26,14 @@ uniform int VertexJWOffset;
uniform mat4 Joints[3]; uniform mat4 Joints[3];
uniform mat4 light_transform;
uniform mat4 world_transform; uniform mat4 world_transform;
uniform mat4 transform; uniform mat4 transform;
varying vec4 PixelNormal; varying vec4 PixelNormal;
varying vec4 PixelTexture; varying vec4 PixelTexture;
varying vec4 PixelWorldPosition; varying vec4 PixelWorldPosition;
varying vec4 PixelLightPosition;
void vertexmain() void vertexmain()
{ {
@ -49,7 +51,8 @@ void vertexmain()
PixelTexture = VertexPNT.Texture; PixelTexture = VertexPNT.Texture;
vec4 Position = mSkin * vec4(VertexPNT.Position.xyz, 1); vec4 Position = mSkin * vec4(VertexPNT.Position.xyz, 1);
//vec4 Position = Joints * vec4(VertexPNT.Position.xyz, 1);
PixelWorldPosition = world_transform * Position; PixelWorldPosition = world_transform * Position;
PixelLightPosition = light_transform * Position;
love_Position = transform * Position; love_Position = transform * Position;
} }

View File

@ -14,11 +14,13 @@ layout (std430) readonly buffer VertexPNTLayout
uniform int VertexPNTOffset; uniform int VertexPNTOffset;
uniform mat4 world_transform; uniform mat4 world_transform;
uniform mat4 light_transform;
uniform mat4 transform; uniform mat4 transform;
varying vec4 PixelNormal; varying vec4 PixelNormal;
varying vec4 PixelTexture; varying vec4 PixelTexture;
varying vec4 PixelWorldPosition; varying vec4 PixelWorldPosition;
varying vec4 PixelLightPosition;
void vertexmain() void vertexmain()
{ {
@ -27,7 +29,9 @@ void vertexmain()
PixelNormal = world_transform * vec4(VertexPNT.Normal.xyz, 0); PixelNormal = world_transform * vec4(VertexPNT.Normal.xyz, 0);
PixelTexture = VertexPNT.Texture; PixelTexture = VertexPNT.Texture;
PixelWorldPosition = world_transform * vec4(VertexPNT.Position.xyz, 1); vec4 Position = vec4(VertexPNT.Position.xyz, 1);
love_Position = transform * vec4(VertexPNT.Position.xyz, 1); PixelWorldPosition = world_transform * Position;
PixelLightPosition = light_transform * Position;
love_Position = transform * Position;
} }