Fix many issues related to shadows.

This commit is contained in:
Alberto Torres 2024-09-21 02:09:22 +02:00
parent 1640040f93
commit dca0123f13
4 changed files with 41 additions and 4 deletions

View file

@ -208,7 +208,7 @@ proc initShader*(self: Shader, engine: MyouEngine, material: Material,
@[ @[
&"precision {precision} float;", &"precision {precision} float;",
&"precision {precision} int;", &"precision {precision} int;",
&"precision {precision} sampler2DShadow;", &"precision {precision} sampler2DArrayShadow;",
] ]
else: else:
@[] @[]
@ -438,6 +438,7 @@ proc initShader*(self: Shader, engine: MyouEngine, material: Material,
if success == 0: if success == 0:
let gl_log = get_shader_info_log(fragment_shader) let gl_log = get_shader_info_log(fragment_shader)
let error_msg = &"Error compiling fragment shader of material {material.name}\n{gl_log}" let error_msg = &"Error compiling fragment shader of material {material.name}\n{gl_log}"
echo error_msg
# console_error fragment # console_error fragment
let lines = fragment.split("\n") let lines = fragment.split("\n")
if "ERROR: 0:" in gl_log: 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): for i in max(1, line - 1000) ..< min(line + 4, lines.len):
console_error(&"{i} {lines[i - 1]}") console_error(&"{i} {lines[i - 1]}")
else: else:
for i in 1 ..< lines.len: for i,line in lines:
console_error(&"{i} {lines[i - 1]}") console_error(&"{i+1} {line}")
console_error(error_msg) console_error(error_msg)
return return
glGetProgramiv(prog, GL_LINK_STATUS, addr success) glGetProgramiv(prog, GL_LINK_STATUS, addr success)

View file

@ -33,6 +33,7 @@
import ../types import ../types
import vmath except Quat import vmath except Quat
import ../util import ../util
import ../graphics/material
when defined(nimdoc): when defined(nimdoc):
type TYPES* = LightType | Light type TYPES* = LightType | Light
@ -100,6 +101,9 @@ proc newLight*(engine: MyouEngine, name: string="",
scene.add_object(this, name=name) scene.add_object(this, name=name)
return this return this
when defined(myouDebugShadows):
var debug_mesh: Mesh
proc configure_shadow*(self: Light, proc configure_shadow*(self: Light,
camera: Camera = nil, camera: Camera = nil,
max_distance: float32 = 0.0, 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 # TODO: instead of a ground plane, we can just exclude the largest
# convex object, as long as we can clamp the polygons outside the # convex object, as long as we can clamp the polygons outside the
# frustum. Can we avoid clipping by setting W? # frustum. Can we avoid clipping by setting W?
self.scene.update_all_matrices() self.scene.update_all_matrices()
var casters: seq[Vec3] var casters: seq[Vec3]
for ob in self.scene.children: for ob in objects:
if not (ob.is_mesh and ob.visible): if not (ob.is_mesh and ob.visible):
continue continue
let me = ob.get_mesh let me = ob.get_mesh
let bb = me.bound_box 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 let world_dim = (ob.world_matrix * vec4(bb[1] - bb[0], 0.0)).xyz
var casts = true var casts = true
if world_dim.z < 0.00001: if world_dim.z < 0.00001:
@ -155,9 +162,29 @@ proc configure_shadow*(self: Light,
break break
casts = not all_above casts = not all_above
if casts: if casts:
echo "adding casting ", ob.name
for v in box_corners(bb): for v in box_corners(bb):
casters.add ob.world_matrix * v 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) casters = quickhull_points(casters)
let shadow = newSimpleShadowManager(self, use_camera = false) let shadow = newSimpleShadowManager(self, use_camera = false)
shadow.caster_bounding_points = casters shadow.caster_bounding_points = casters

View file

@ -38,6 +38,12 @@ proc updateShadowStorage*(scene: Scene) =
let fb_size = scene.shadow_map_resolution let fb_size = scene.shadow_map_resolution
assert color_channels <= 4 assert color_channels <= 4
if scene.shadow_maps != nil: 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.destroy()
scene.shadow_maps = scene.engine.newFramebuffer(fb_size, fb_size, scene.shadow_maps = scene.engine.newFramebuffer(fb_size, fb_size,
if color_channels != 0: if color_channels != 0:

View file

@ -97,6 +97,8 @@ proc newSimpleShadowManager*(light: Light;
self.uses_depth = false self.uses_depth = false
when defined(myouDebugShadows): when defined(myouDebugShadows):
if debug_mesh != nil:
debug_mesh.destroy()
debug_mesh = self.engine.newMesh(vertex_count = 100, draw_method = Lines) 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.materials.add self.engine.newSolidMaterial("green", vec4(0,1,0,1))
debug_mesh.visible = false debug_mesh.visible = false
@ -105,6 +107,7 @@ proc newSimpleShadowManager*(light: Light;
method destroy*(self: SimpleShadowManager) {.locks:"unknown".} = method destroy*(self: SimpleShadowManager) {.locks:"unknown".} =
if self.material != nil: if self.material != nil:
self.material.destroy() self.material.destroy()
debug_mesh.destroy()
when defined(myouDebugShadows): when defined(myouDebugShadows):
proc show_mat(mat: Mat4) = proc show_mat(mat: Mat4) =