screen-space sobel filter

This commit is contained in:
Zack Buhman 2026-02-26 22:45:53 +00:00
parent a2f4a31dcf
commit 85174f15f6
8 changed files with 1762 additions and 834 deletions

View File

@ -17,8 +17,35 @@ local scene_sci_fi_ship = require 'scene.sci_fi_ship.sci_fi_ship'
local node_state local node_state
local g_position_canvas
local g_normal_canvas
local screen_index_buffer
local screen_shader
local load_screen_index_buffer = function()
local screen_index_data = love.data.newByteData(3 * 2 * 4)
local ptr = ffi.cast('uint32_t*', screen_index_data:getFFIPointer())
ptr[0] = 0
ptr[1] = 1
ptr[2] = 2
ptr[3] = 0
ptr[4] = 2
ptr[5] = 3
screen_index_buffer = love.graphics.newBuffer("uint32", screen_index_data, { index = true, usage = "static" })
end
local load_screen_shader = function()
load_screen_index_buffer()
local pixel_data = love.filesystem.newFileData("pixel_sobel.glsl")
local vertex_data = love.filesystem.newFileData("vertex_sobel.glsl")
screen_shader = love.graphics.newShader(pixel_data, vertex_data)
end
function love.load(args) function love.load(args)
love.window.setMode(1024, 1024, {depth=true}) love.window.setMode(1024, 1024, {depth=true, resizable=false})
local scene = scene_sci_fi_ship local scene = scene_sci_fi_ship
@ -28,6 +55,16 @@ function love.load(args)
collada_scene.load_buffers(idx_path, vtx_path, vjw_path) collada_scene.load_buffers(idx_path, vtx_path, vjw_path)
collada_scene.load_images("scene/sci_fi_ship", scene.descriptor.images) collada_scene.load_images("scene/sci_fi_ship", scene.descriptor.images)
node_state = collada_scene_node_state(scene.descriptor.nodes) node_state = collada_scene_node_state(scene.descriptor.nodes)
----------------------------------------------------------------------
-- canvas
----------------------------------------------------------------------
g_position_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"})
load_screen_shader()
end end
local rotation = 0.0 local rotation = 0.0
@ -49,15 +86,33 @@ function love.draw()
vec3(0.0, 0.0, 13.41141), vec3(0.0, 0.0, 13.41141),
vec3(0, 0, 1)) vec3(0, 0, 1))
local world1 = mat4.rotation_x(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
local transform = view * projection local transform = view * projection
collada_scene_animate.update(t, node_state) collada_scene_animate.update(t, node_state)
t = t + 0.016 t = t + 0.016
love.graphics.setBlendMode("replace", "premultiplied")
love.graphics.setDepthMode("less", true) love.graphics.setDepthMode("less", true)
love.graphics.setCanvas({
g_color_canvas,
g_position_canvas,
g_normal_canvas,
depth = true
})
love.graphics.clear(
{0.0, 0.0, 0.0, 1.0},
{0.0, 0.0, 0.0, 1.0},
{0.0, 0.0, 0.0, 1.0})
collada_scene.draw_nodes(node_state, transform) collada_scene.draw_nodes(node_state, transform)
love.graphics.setCanvas()
love.graphics.setShader(screen_shader)
screen_shader:send("g_normal_sampler", g_normal_canvas)
screen_shader:send("g_color_sampler", g_color_canvas)
love.graphics.drawFromShader(screen_index_buffer, 3 * 2, 1, 1)
end end

View File

@ -19,7 +19,9 @@ uniform vec4 view_position;
uniform vec4 light_position; uniform vec4 light_position;
uniform ivec4 texture_channel; uniform ivec4 texture_channel;
out vec4 out_color; layout (location = 0) out vec4 g_color;
layout (location = 1) out vec4 g_position;
layout (location = 2) out vec4 g_normal;
void pixelmain() void pixelmain()
{ {
@ -61,5 +63,7 @@ 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;
out_color = vec4(color, 1.0); g_position = vec4(PixelWorldPosition.xyz * 0.0005 + 0.5, 0.0);
g_normal = vec4(normal * 0.5 + 0.5, PixelWorldPosition.z * 0.001 + 0.5);
g_color = vec4(color, 1.0);
} }

60
pixel_sobel.glsl Normal file
View File

@ -0,0 +1,60 @@
#pragma language glsl3
uniform sampler2D g_position_sampler;
uniform sampler2D g_normal_sampler;
uniform sampler2D g_color_sampler;
varying vec4 PixelTexture;
out vec4 out_color;
mat3 sobel_x = mat3( 1.0, 2.0, 1.0,
0.0, 0.0, 0.0,
-1.0, -2.0, -1.0);
mat3 sobel_y = mat3(1.0, 0.0, -1.0,
2.0, 0.0, -2.0,
1.0, 0.0, -1.0);
float sobel(mat3 K)
{
float sx = dot(sobel_x[0], K[0]) + dot(sobel_x[1], K[1]) + dot(sobel_x[2], K[2]);
float sy = dot(sobel_y[0], K[0]) + dot(sobel_y[1], K[1]) + dot(sobel_y[2], K[2]);
float edge = sqrt(pow(sx, 2.0) + pow(sy, 2.0));
//float edge = max(sx, sy);
return edge;
}
float kernel()
{
mat3 K;
mat3 Kz;
//mat3 Kx;
//mat3 Ky;
//mat3 Kz;
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
vec4 sample = texelFetch(g_normal_sampler, ivec2(gl_FragCoord) + ivec2(x-1, y-1), 0);
//Kx[x][y] = sample.x;
//Ky[x][y] = sample.y;
//Kz[x][y] = sample.z;
K[x][y] = length(sample.xyz);
}
}
//return max(sobel(Kx), max(sobel(Ky), sobel(Kz)));
return float(sobel(K) < 0.1);
}
void pixelmain()
{
vec4 color = texelFetch(g_color_sampler, ivec2(gl_FragCoord), 0);
if (color.xyz == vec3(0, 0, 0)) {
out_color = vec4(0.1, 0.1, 0.2, 1.0);
} else {
float edge = kernel();
out_color = vec4(edge * color.xyz, 1.0);
//out_color = vec4(edge, edge, edge, 1.0);
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

17
vertex_sobel.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;
}