From dca0123f13857ba855d4452865f664ec0dddbb08 Mon Sep 17 00:00:00 2001 From: Alberto Torres Date: Sat, 21 Sep 2024 02:09:22 +0200 Subject: [PATCH] Fix many issues related to shadows. --- src/graphics/material.nim | 7 ++++--- src/objects/light.nim | 29 ++++++++++++++++++++++++++++- src/shadows/shadow_common.nim | 6 ++++++ src/shadows/simple_shadow.nim | 3 +++ 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/graphics/material.nim b/src/graphics/material.nim index 6a21bba..c82b7bb 100644 --- a/src/graphics/material.nim +++ b/src/graphics/material.nim @@ -208,7 +208,7 @@ proc initShader*(self: Shader, engine: MyouEngine, material: Material, @[ &"precision {precision} float;", &"precision {precision} int;", - &"precision {precision} sampler2DShadow;", + &"precision {precision} sampler2DArrayShadow;", ] else: @[] @@ -438,6 +438,7 @@ proc initShader*(self: Shader, engine: MyouEngine, material: Material, if success == 0: let gl_log = get_shader_info_log(fragment_shader) let error_msg = &"Error compiling fragment shader of material {material.name}\n{gl_log}" + echo error_msg # console_error fragment let lines = fragment.split("\n") if "ERROR: 0:" in gl_log: @@ -452,8 +453,8 @@ proc initShader*(self: Shader, engine: MyouEngine, material: Material, for i in max(1, line - 1000) ..< min(line + 4, lines.len): console_error(&"{i} {lines[i - 1]}") else: - for i in 1 ..< lines.len: - console_error(&"{i} {lines[i - 1]}") + for i,line in lines: + console_error(&"{i+1} {line}") console_error(error_msg) return glGetProgramiv(prog, GL_LINK_STATUS, addr success) diff --git a/src/objects/light.nim b/src/objects/light.nim index e69e202..091e3c7 100644 --- a/src/objects/light.nim +++ b/src/objects/light.nim @@ -33,6 +33,7 @@ import ../types import vmath except Quat import ../util +import ../graphics/material when defined(nimdoc): type TYPES* = LightType | Light @@ -100,6 +101,9 @@ proc newLight*(engine: MyouEngine, name: string="", scene.add_object(this, name=name) return this +when defined(myouDebugShadows): + var debug_mesh: Mesh + proc configure_shadow*(self: Light, camera: Camera = nil, max_distance: float32 = 0.0, @@ -131,13 +135,16 @@ proc configure_shadow*(self: Light, # TODO: instead of a ground plane, we can just exclude the largest # convex object, as long as we can clamp the polygons outside the # frustum. Can we avoid clipping by setting W? + self.scene.update_all_matrices() var casters: seq[Vec3] - for ob in self.scene.children: + for ob in objects: if not (ob.is_mesh and ob.visible): continue let me = ob.get_mesh let bb = me.bound_box + if bb[0] == bb[1]: + continue let world_dim = (ob.world_matrix * vec4(bb[1] - bb[0], 0.0)).xyz var casts = true if world_dim.z < 0.00001: @@ -155,9 +162,29 @@ proc configure_shadow*(self: Light, break casts = not all_above if casts: + echo "adding casting ", ob.name for v in box_corners(bb): casters.add ob.world_matrix * v + if casters.len == 0: + return + when defined(myouDebugShadows): + if debug_mesh.nonNil: + debug_mesh.destroy() + debug_mesh = self.engine.newMesh(vertex_count = 100, draw_method = Lines) + debug_mesh.materials.add self.engine.newSolidMaterial("green", vec4(0,1,0,1)) + debug_mesh.visible = true + self.scene.add_object debug_mesh + + let hull = quickhull(casters) + for f in hull: + debug_mesh.add_vertex f.points[0], vec4(1) + for v in f.points[1..^1]: + debug_mesh.add_vertex v, vec4(1) + debug_mesh.add_vertex v, vec4(1) + debug_mesh.add_vertex f.points[0], vec4(1) + debug_mesh.data.update_varray() + casters = quickhull_points(casters) let shadow = newSimpleShadowManager(self, use_camera = false) shadow.caster_bounding_points = casters diff --git a/src/shadows/shadow_common.nim b/src/shadows/shadow_common.nim index b10aa8c..9d82b74 100644 --- a/src/shadows/shadow_common.nim +++ b/src/shadows/shadow_common.nim @@ -38,6 +38,12 @@ proc updateShadowStorage*(scene: Scene) = let fb_size = scene.shadow_map_resolution assert color_channels <= 4 if scene.shadow_maps != nil: + # TODO: we're assuming that if it exists it has all the same parameters + # and that only resolution and number of layers will change + if scene.shadow_maps.width == fb_size and + scene.shadow_maps.layer_count == count: + scene.calculate_max_lights_and_cubemaps() + return scene.shadow_maps.destroy() scene.shadow_maps = scene.engine.newFramebuffer(fb_size, fb_size, if color_channels != 0: diff --git a/src/shadows/simple_shadow.nim b/src/shadows/simple_shadow.nim index 2b2372d..be0eb03 100644 --- a/src/shadows/simple_shadow.nim +++ b/src/shadows/simple_shadow.nim @@ -97,6 +97,8 @@ proc newSimpleShadowManager*(light: Light; self.uses_depth = false when defined(myouDebugShadows): + if debug_mesh != nil: + debug_mesh.destroy() debug_mesh = self.engine.newMesh(vertex_count = 100, draw_method = Lines) debug_mesh.materials.add self.engine.newSolidMaterial("green", vec4(0,1,0,1)) debug_mesh.visible = false @@ -105,6 +107,7 @@ proc newSimpleShadowManager*(light: Light; method destroy*(self: SimpleShadowManager) {.locks:"unknown".} = if self.material != nil: self.material.destroy() + debug_mesh.destroy() when defined(myouDebugShadows): proc show_mat(mat: Mat4) =