Skip to content

Instantly share code, notes, and snippets.

@KonnorRogers
Created June 11, 2026 05:02
Show Gist options
  • Select an option

  • Save KonnorRogers/1869a90c401174ab4211eed8831fa25b to your computer and use it in GitHub Desktop.

Select an option

Save KonnorRogers/1869a90c401174ab4211eed8831fa25b to your computer and use it in GitHub Desktop.
glow outline blendmode dragonruby
# one-time setup
@glow_dirs ||= 16.times.map do |i|
a = i * Math::PI * 2 / 16
[Math.cos(a), Math.sin(a)]
end
@glow_mask_blend ||= Numeric.compose_blendmode(
BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA, BLENDOPERATION_ADD,
BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA, BLENDOPERATION_ADD
)
@glow_hole_punch ||= Numeric.compose_blendmode(
BLENDFACTOR_ZERO, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, BLENDOPERATION_ADD,
BLENDFACTOR_ZERO, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, BLENDOPERATION_ADD
)
# additive that also accumulates alpha (blendmode_enum 2 leaves dst alpha at 0,
# which made the final composite invisible)
@glow_add ||= Numeric.compose_blendmode(
BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE, BLENDOPERATION_ADD,
BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDOPERATION_ADD
)
@glow_dirs ||= [[1, 0], [-1, 0], [0, 1], [0, -1],
[0.7, 0.7], [-0.7, 0.7], [0.7, -0.7], [-0.7, -0.7]]
# @glow_rings ||= [[1.5, 200]] # [offset radius px, alpha]; add [7, 60] back for a soft halo
@glow_rings ||= [[2, 255], [4, 255], [6, 180]] # solid ~6px outline, fading at the rim
@glow_color ||= { r: 50, g: 230, b: 255 }
occluding = (@objects_in_viewport + @entities_in_viewport).select do |obj|
obj.y < @player.y && Geometry.intersect_rect?(obj, @player)
end
if !occluding.empty?
# player mask
args.outputs[:glow_player].set w: 1280, h: 720, background_color: [0, 0, 0, 0]
args.outputs[:glow_player].primitives.concat(
@player.prefab.map { |spr| @camera.to_screen_space!(spr.dup) }
)
# occluder mask
args.outputs[:glow_occ].set w: 1280, h: 720, background_color: [0, 0, 0, 0]
args.outputs[:glow_occ].primitives.concat(
occluding.flat_map(&:prefab).map { |spr| @camera.to_screen_space!(spr.dup) }
)
# hidden = player ∧ occluder (multiply whole RT by occluder alpha)
args.outputs[:glow_hidden].set w: 1280, h: 720, background_color: [0, 0, 0, 0]
args.outputs[:glow_hidden].primitives << { x: 0, y: 0, w: 1280, h: 720, path: :glow_player }
args.outputs[:glow_hidden].primitives << { x: 0, y: 0, w: 1280, h: 720,
path: :glow_occ, blendmode: @glow_mask_blend }
# glow = dilated copies of hidden, interior punched out
args.outputs[:glow_rt].set w: 1280, h: 720, background_color: [0, 0, 0, 0]
@glow_rings.each do |radius, alpha|
@glow_dirs.each do |dx, dy|
args.outputs[:glow_rt].primitives << {
x: dx * radius, y: dy * radius, w: 1280, h: 720, path: :glow_hidden,
**@glow_color, a: alpha, blendmode: @glow_add
}
end
end
args.outputs[:glow_rt].primitives << { x: 0, y: 0, w: 1280, h: 720,
path: :glow_hidden, blendmode: @glow_hole_punch }
# composite onto the screen
args.outputs.primitives << { x: 0, y: 0, w: 1280, h: 720,
path: :glow_rt, blendmode_enum: 2 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment