diff --git a/Actors/Objects/Lightbulb/Lightbulb.gd b/Actors/Objects/Lightbulb/Lightbulb.gd index abe5412..7939d23 100644 --- a/Actors/Objects/Lightbulb/Lightbulb.gd +++ b/Actors/Objects/Lightbulb/Lightbulb.gd @@ -45,7 +45,6 @@ func refresh_sprite(): Direction.RIGHT: $light.region_rect.position = Vector2(64, lit_offset) rot = PI/2 - $Light2D.rotation = rot $ActivationRange.rotation = rot @@ -61,4 +60,4 @@ func _power_status_changed(_powered: bool) -> void: refresh_sprite() func update_light(): - $Light2D.enabled = lit and (manager != null and manager.powered) + pass diff --git a/Actors/Objects/Lightbulb/Lightbulb.tscn b/Actors/Objects/Lightbulb/Lightbulb.tscn index 25b0958..f6f3cf5 100644 --- a/Actors/Objects/Lightbulb/Lightbulb.tscn +++ b/Actors/Objects/Lightbulb/Lightbulb.tscn @@ -1,6 +1,5 @@ -[gd_scene load_steps=8 format=2] +[gd_scene load_steps=7 format=2] -[ext_resource path="res://Graphics/light_shadow_light.png" type="Texture" id=1] [ext_resource path="res://Graphics/tgstation/light.png" type="Texture" id=2] [ext_resource path="res://Actors/Objects/Lightbulb/Lightbulb.gd" type="Script" id=3] [ext_resource path="res://Actors/Components/ActivationRange.gd" type="Script" id=4] @@ -23,19 +22,6 @@ texture = ExtResource( 2 ) region_enabled = true region_rect = Rect2( 32, 0, 32, 32 ) -[node name="Light2D" type="Light2D" parent="."] -enabled = false -texture = ExtResource( 1 ) -texture_scale = 3.5 -energy = 1.2 -mode = 2 -shadow_color = Color( 0, 0, 0, 1 ) -shadow_filter_smooth = 10.0 -__meta__ = { -"_edit_group_": true, -"_edit_lock_": true -} - [node name="ActivationRange" type="Area2D" parent="."] visible = false script = ExtResource( 4 ) diff --git a/Scenes/Game.gd b/Scenes/Game.gd index 532f944..a7550f0 100644 --- a/Scenes/Game.gd +++ b/Scenes/Game.gd @@ -3,11 +3,13 @@ extends Node class_name GameInstance onready var ui = $CanvasLayer/ui +onready var lighting = $CanvasLayer/sslo onready var world = $world onready var systems = $systems func _ready(): ui.connect("command", world, "process_command") + world.initiate() func process_command(cmd: UICommand): match cmd.cmd_type: diff --git a/Scenes/Map.gd b/Scenes/Map.gd index 998ae47..84fd981 100644 --- a/Scenes/Map.gd +++ b/Scenes/Map.gd @@ -20,7 +20,6 @@ onready var tilemaps = [ $base, $cables, $floor, $walls ] onready var pois = $pois export var unlit = false setget set_unlit -onready var darkness = $darkness export var shadow_intensity = 0.2 @@ -54,8 +53,6 @@ func _process(delta: float): func set_unlit(val: bool): unlit = val - if darkness: - darkness.visible = not val # Engine related functions diff --git a/Scenes/Maps/odyssey.gd b/Scenes/Maps/odyssey.gd index a2b9ff4..a4ba1e7 100644 --- a/Scenes/Maps/odyssey.gd +++ b/Scenes/Maps/odyssey.gd @@ -7,3 +7,9 @@ func _ready(): $floor, $walls ] + +func get_occlusion_mask(): + return $walls.create_occlusion_mask() + +func get_occlusion_offset(): + return $walls.get_used_rect().position diff --git a/Scenes/Maps/odyssey.tscn b/Scenes/Maps/odyssey.tscn index ebbd860..5d389d5 100644 --- a/Scenes/Maps/odyssey.tscn +++ b/Scenes/Maps/odyssey.tscn @@ -22,10 +22,6 @@ light_mode = 1 [node name="map" type="Node2D"] script = ExtResource( 5 ) -[node name="darkness" type="CanvasModulate" parent="."] -visible = false -color = Color( 0, 0, 0, 1 ) - [node name="editor" type="Node2D" parent="."] [node name="deepspace" type="Sprite" parent="."] @@ -92,14 +88,17 @@ __meta__ = { [node name="Engine" parent="engines" instance=ExtResource( 10 )] position = Vector2( -320, 321 ) direction = 0 +strength = 1.0 [node name="Engine2" parent="engines" instance=ExtResource( 10 )] position = Vector2( -480, 208 ) direction = 0 +strength = 1.0 [node name="Engine3" parent="engines" instance=ExtResource( 10 )] position = Vector2( -320, 96 ) direction = 0 +strength = 1.0 [node name="objects" type="Node2D" parent="."] z_index = 10 @@ -450,10 +449,6 @@ flow = 1 [node name="lights" type="Node2D" parent="."] modulate = Color( 0.980392, 0.980392, 0.980392, 1 ) z_index = 11 -__meta__ = { -"_edit_group_": true, -"_edit_lock_": true -} [node name="Lighttube" parent="lights" instance=ExtResource( 8 )] position = Vector2( 80, 144 ) diff --git a/Scenes/Rendering/MapTiles.gd b/Scenes/Rendering/MapTiles.gd index cf94833..f511a7f 100644 --- a/Scenes/Rendering/MapTiles.gd +++ b/Scenes/Rendering/MapTiles.gd @@ -13,13 +13,9 @@ export var shadow_intensity = 0.2 onready var extended_tilemap = get_node(extended_tilemap_node) as TileMap func _ready(): - # Make occluders - make_occluders() - # Convert 2x2 tiles to 1x1 if possible convert_extended() - func convert_extended(): var extended = extended_tilemap.tile_set for id in tile_set.get_tiles_ids(): @@ -40,31 +36,20 @@ func convert_extended(): extended_tilemap.update_bitmask_region() extended_tilemap.update_dirty_quadrants() -func make_occluders(): +func create_occlusion_mask(): + var tile_size = get_used_rect() + var mask_image = Image.new() + mask_image.create(tile_size.size.x, tile_size.size.y, false, Image.FORMAT_L8) + mask_image.fill(Color.black) + mask_image.lock() var occluder_ids = [] - for occluder_name in occluders: - var id = tile_set.find_tile_by_name(occluder_name) - if id >= 0: - occluder_ids.push_back(id) - for id in tile_set.get_tiles_ids(): - if occluder_ids.find(id) < 0: - # Not an occluder, skip it - continue - # Find all uses of this tile - for cell in get_used_cells_by_id(id): - # Check sides - var occluder = Occluder.new() - occluder.ignore_sides = [ - occluder_ids.find(get_cell(cell.x, cell.y-1)) >= 0, # Top - occluder_ids.find(get_cell(cell.x+1, cell.y)) >= 0, # Right - occluder_ids.find(get_cell(cell.x, cell.y+1)) >= 0, # Bottom - occluder_ids.find(get_cell(cell.x-1, cell.y)) >= 0 # Left - ] - occluder.transform.origin = map_to_world(cell) - add_child(occluder) - - -func set_occluder_origin(origin): - for child in get_children(): - if child is Occluder: - child.origin = origin + for occluder in occluders: + occluder_ids.append(tile_set.find_tile_by_name(occluder)) + for occluder_id in occluder_ids: + for cell in get_used_cells_by_id(occluder_id): + mask_image.set_pixelv(cell - tile_size.position, Color.white) + mask_image.unlock() + mask_image.save_png("res://test.png") + var mask_texture = ImageTexture.new() + mask_texture.create_from_image(mask_image, 0) + return mask_texture diff --git a/Scenes/Rendering/Occluder.gd b/Scenes/Rendering/Occluder.gd deleted file mode 100644 index 87f0155..0000000 --- a/Scenes/Rendering/Occluder.gd +++ /dev/null @@ -1,52 +0,0 @@ -extends Node2D - -class_name Occluder - -const MAX_LENGTH = 200 -const EPSILON = 0.1 -const DEBUG = false - -var ignore_sides = [false, false, false, false] -var size = Vector2(32, 32) -var origin = null -var polygon: PoolVector2Array = [Vector2.ZERO, Vector2(size.x, 0), Vector2(size.x, size.y), Vector2(0, size.y)] - -func _draw(): - if polygon == null: - return - - if origin == null: - return - - var player_position = origin.global_position - global_position - - # Find what edges is the players looking at - var edges = [ - player_position.y < 0, # TOP - player_position.x > size.x*2, # RIGHT - player_position.y > size.y*2, # BOTTOM - player_position.x < 0 # LEFT - ] - - for current in range(0, polygon.size()): - var next = (current + 1) % polygon.size() - - if not ignore_sides[current] and not edges[current]: - var points = [ - (polygon[current] * 2.1 - origin.global_position + global_position) * MAX_LENGTH, - polygon[current], polygon[next], - (polygon[next] * 2.1 - origin.global_position + global_position) * MAX_LENGTH - ] - draw_polygon(points, [Color.black]) - if DEBUG: - draw_polyline(points, Color.rebeccapurple) - else: - if DEBUG: - if ignore_sides[current]: - draw_line(polygon[current], polygon[next], Color.red, 1) - else: - draw_line(polygon[current], polygon[next], Color.yellow, 2) - -func _process(_delta): - update() - z_index = 999 diff --git a/Scenes/Rendering/SSLO.gd b/Scenes/Rendering/SSLO.gd new file mode 100644 index 0000000..d4fadfe --- /dev/null +++ b/Scenes/Rendering/SSLO.gd @@ -0,0 +1,15 @@ +extends ColorRect + +var player = null +var occlusion_mask: ImageTexture = null +var occlusion_offset = Vector2.ZERO + +onready var shader = (material as ShaderMaterial) + +func _process(delta): + if occlusion_mask != null: + shader.set_shader_param("occlusion_mask", occlusion_mask) + shader.set_shader_param("occlusion_rect", Color(occlusion_offset.x, occlusion_offset.y, occlusion_mask.get_width(), occlusion_mask.get_height())) + var viewport_rect = get_viewport_rect() + var camera_offset = player.camera.get_camera_position() - viewport_rect.size * 0.5 + shader.set_shader_param("viewport_rect", Color(camera_offset.x, camera_offset.y, viewport_rect.size.x, viewport_rect.size.y)) diff --git a/Scenes/Rendering/SSLO.shader b/Scenes/Rendering/SSLO.shader new file mode 100644 index 0000000..7efa73e --- /dev/null +++ b/Scenes/Rendering/SSLO.shader @@ -0,0 +1,34 @@ +shader_type canvas_item; +render_mode unshaded; + +uniform vec4 viewport_rect; +uniform sampler2D occlusion_mask; +uniform vec4 occlusion_rect; +uniform float cell_div = 0.03125; // 1/cell_size = 1/32 +uniform float diffusion = 0.3; +uniform float scale_factor = 0.5; + +float tile_at(vec2 coord, vec2 camera_tile_offset, vec2 occlusion_div) { + return texture(occlusion_mask, (coord * cell_div - occlusion_rect.xy) * occlusion_div + camera_tile_offset).r; +} + +void fragment() { + vec2 occlusion_div = 1.0 / occlusion_rect.zw; + vec2 camera_offset = viewport_rect.xy * scale_factor; + vec2 camera_tile_offset = camera_offset * cell_div * occlusion_div; + + vec2 coords = UV.xy * viewport_rect.zw * scale_factor; + float tile = tile_at(coords, camera_tile_offset, occlusion_div); + + vec4 ray_coords = vec4(0,0, viewport_rect.zw/2.) * scale_factor; + vec2 ray_dir = normalize(ray_coords.zw - ray_coords.xy); + if (int(coords.x+camera_offset.x) % 32 < 1 || int(coords.y+camera_offset.y) % 32 < 1) { + COLOR = vec4(1); + } else if (distance(coords, ray_coords.xy) < 10.0 || distance(coords, ray_coords.zw) < 10.) { + COLOR = vec4(0,1,0,1); + } else if (tile >= diffusion) { + COLOR = vec4(1,0,0,1); + } else { + COLOR = texture(SCREEN_TEXTURE, SCREEN_UV); + } +} \ No newline at end of file diff --git a/Scenes/SSLOTest.tscn b/Scenes/SSLOTest.tscn new file mode 100644 index 0000000..faeb80f --- /dev/null +++ b/Scenes/SSLOTest.tscn @@ -0,0 +1,92 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://Scenes/Maps/odyssey.tscn" type="PackedScene" id=1] +[ext_resource path="res://Scenes/Rendering/SSLO.shader" type="Shader" id=2] +[ext_resource path="res://Scenes/UI.tscn" type="PackedScene" id=3] +[ext_resource path="res://Scenes/Rendering/SSLO.gd" type="Script" id=4] +[ext_resource path="res://Scenes/Game.gd" type="Script" id=5] +[ext_resource path="res://test.png" type="Texture" id=6] + +[sub_resource type="GDScript" id=1] +script/source = "extends Node2D + +enum Map { RUNTIME, ODYSSEY } + +export(Map) var mapToLoad = Map.RUNTIME + +const playerRes = preload(\"res://Actors/Player/Player.tscn\") + +var map = null +var player = null + +func initiate(): + player = playerRes.instance() + player.is_controlled = true + map = $map + var spawnpoints = map.get_pois(POIData.POIType.SpawnPoint, POIData.POIClass.Player) + if spawnpoints.size() > 0: + player.transform.origin = (spawnpoints[0] as Node2D).transform.origin + else: + print(\"Map does not have Player spawnpoint POI! Spawning at origin (very bad)\") + $players.add_child(player) + $\"/root/scene\".lighting.player = player + var occlusion_mask = map.get_occlusion_mask() + $\"/root/scene\".lighting.occlusion_mask = occlusion_mask + $\"/root/scene\".lighting.occlusion_offset = map.get_occlusion_offset() + print(map.get_occlusion_offset()) + ($\"/root/scene/CanvasLayer/TextureRect\" as TextureRect).texture = occlusion_mask + +func initiate_editor(): + map = $map + var occlusion_mask = map.get_occlusion_mask() + $\"/root/scene\".lighting.occlusion_mask = occlusion_mask + ($\"/root/scene/CanvasLayer/TextureRect\" as TextureRect).texture = occlusion_mask +" + +[sub_resource type="ShaderMaterial" id=2] +shader = ExtResource( 2 ) +shader_param/viewport_rect = Plane( 0, 0, 1280, 800 ) +shader_param/occlusion_rect = Plane( -12, -9, 32, 33 ) +shader_param/cell_div = 0.03125 +shader_param/diffusion = 0.3 +shader_param/scale_factor = 0.5 +shader_param/occlusion_mask = ExtResource( 6 ) + +[node name="scene" type="Node"] +script = ExtResource( 5 ) + +[node name="systems" type="Node" parent="."] + +[node name="world" type="Node2D" parent="."] +scale = Vector2( 2, 2 ) +script = SubResource( 1 ) + +[node name="map" parent="world" instance=ExtResource( 1 )] + +[node name="players" type="Node2D" parent="world"] + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="TextureRect" type="TextureRect" parent="CanvasLayer"] +visible = false +margin_right = 20.0 +margin_bottom = 15.0 +rect_scale = Vector2( 4, 4 ) +mouse_filter = 2 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="sslo" type="ColorRect" parent="CanvasLayer"] +material = SubResource( 2 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +color = Color( 0, 0, 0, 0.764706 ) +script = ExtResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ui" parent="CanvasLayer" instance=ExtResource( 3 )] +visible = false diff --git a/project.godot b/project.godot index e43245f..9699197 100644 --- a/project.godot +++ b/project.godot @@ -69,11 +69,6 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://Scenes/Rendering/MapTiles.gd" }, { -"base": "Node2D", -"class": "Occluder", -"language": "GDScript", -"path": "res://Scenes/Rendering/Occluder.gd" -}, { "base": "Reference", "class": "POIData", "language": "GDScript", @@ -117,7 +112,6 @@ _global_script_class_icons={ "GameObjectScanner": "", "GameWorld": "", "MapTiles": "", -"Occluder": "", "POIData": "", "PowerManager": "", "PowerNetwork": "", diff --git a/test.png b/test.png new file mode 100644 index 0000000..e79d9f3 Binary files /dev/null and b/test.png differ diff --git a/test.png.import b/test.png.import new file mode 100644 index 0000000..f8f1de4 --- /dev/null +++ b/test.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/test.png-2b0b935732229e5bd5e655f2644b2498.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://test.png" +dest_files=[ "res://.import/test.png-2b0b935732229e5bd5e655f2644b2498.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0