From 0f1ad758e83796de5de1634ef415a8335a59df07 Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Sun, 21 Jul 2024 14:17:35 -0600 Subject: [PATCH] Hard-edge shader --- project.godot | 6 +--- src/hard_edge.gdshader | 64 ++++++++++++++++++++++++++++++++++++++++++ src/main.tscn | 28 ++++++++++++++++++ 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 src/hard_edge.gdshader create mode 100644 src/main.tscn diff --git a/project.godot b/project.godot index 549a078..b1ec953 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="Sunstation" -run/main_scene="res://src/maps/arena_map/arena_map.tscn" +run/main_scene="res://src/main.tscn" config/features=PackedStringArray("4.2", "Forward Plus") run/max_fps=60 @@ -80,7 +80,3 @@ boost={ , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":true,"script":null) ] } - -[rendering] - -anti_aliasing/quality/msaa_3d=3 diff --git a/src/hard_edge.gdshader b/src/hard_edge.gdshader new file mode 100644 index 0000000..fee8681 --- /dev/null +++ b/src/hard_edge.gdshader @@ -0,0 +1,64 @@ +/* Hard-edge shader + * Adapted from https://github.com/samuelbigos/godot_dither_shader + */ + +shader_type canvas_item; + +// uniform sampler2D dither_tex; +uniform sampler2D color_tex; + +uniform int bit_depth; +uniform float contrast; +uniform float offset; +// uniform int dither_size; + +void fragment() { + //// sample the screen texture at the desired output resolution (according to dither_size) + //// this pixelates the output + //vec2 screen_size = vec2(textureSize(TEXTURE, 0)) / float(dither_size); + //vec2 screen_sample_uv = floor(UV * screen_size) / screen_size; + //vec3 screen_col = texture(TEXTURE, screen_sample_uv).rgb; + vec3 screen_col = texture(TEXTURE, UV).rgb; + + // calculate pixel luminosity + float luminosity = (screen_col.r * 0.299) + (screen_col.g * 0.587) + (screen_col.b * 0.114); + + // adjust contrast & offset + // XXX: need to redefine contrast??? + luminosity = clamp((luminosity - 0.5 + offset) * contrast + 0.5, 0.0, 1.0); + + // reduce luminosity bit depth to increase banding if desired + float b = float(bit_depth); + luminosity = floor(luminosity * b) / b; + + // map palette texture to 1px high + ivec2 col_size = textureSize(color_tex, 0); + col_size /= col_size.y; + + float col_x = float(col_size.x) - 1.0; + float col_texel_size = 1.0 / col_x; // size of one color boundary + + luminosity = max(luminosity - 0.00001, 0.0); // fix for `floor` when luminosity == 1.0 + float lum_lower = floor(luminosity * col_x) * col_texel_size; + float lum_upper = (floor(luminosity * col_x) + 1.0) * col_texel_size; + // fractional portion of scaled luminosity + float lum_scaled = luminosity * col_x - floor(luminosity * col_x); + + //// map dither texture onto screen + //ivec2 noise_size = textureSize(dither_tex, 0); + //vec2 inv_noise_size = vec2(1.0 / float(noise_size.x), 1.0 / float(noise_size.y)); + //vec2 noise_uv = UV * inv_noise_size * vec2(float(screen_size.x), float(screen_size.y)); + //float threshold = texture(dither_tex, noise_uv).r; + + //// add dither margins to allow fully dark and light dither patterns at edges of luminosity + //threshold = threshold * 0.99 + 0.005; + + //// the lower lum_scaled is, the fewer pixels will be below the dither threshold, + //// and thus will use the lower bound color, and vice versa + //float ramp_val = lum_scaled < threshold ? 0.0f : 1.0f; + float ramp_val = lum_scaled < 0.5 ? 0.0f : 1.0f; + // sample at lower bound color if ramp_val is 0.0, upper bound color if 1.0 + float col_sample = mix(lum_lower, lum_upper, ramp_val); + + COLOR.rgb = texture(color_tex, vec2(col_sample, 0.5)).rgb; +} diff --git a/src/main.tscn b/src/main.tscn new file mode 100644 index 0000000..f18bc76 --- /dev/null +++ b/src/main.tscn @@ -0,0 +1,28 @@ +[gd_scene load_steps=5 format=3 uid="uid://d75odchj18u1"] + +[ext_resource type="PackedScene" uid="uid://drbiyuustse8b" path="res://src/maps/arena_map/arena_map.tscn" id="1_bvhtq"] +[ext_resource type="Shader" path="res://src/hard_edge.gdshader" id="1_y05i6"] +[ext_resource type="Texture2D" uid="uid://deu1gf4gxbvvh" path="res://assets/palette_moonlight.png" id="2_uwrk1"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ab1b3"] +shader = ExtResource("1_y05i6") +shader_parameter/bit_depth = 32 +shader_parameter/contrast = 1.0 +shader_parameter/offset = null +shader_parameter/color_tex = ExtResource("2_uwrk1") + +[node name="Main" type="Node3D"] + +[node name="ViewportContainer" type="SubViewportContainer" parent="."] +material = SubResource("ShaderMaterial_ab1b3") +custom_minimum_size = Vector2(1900, 768) +offset_right = 1900.0 +offset_bottom = 768.0 +stretch = true + +[node name="Viewport" type="SubViewport" parent="ViewportContainer"] +handle_input_locally = false +size = Vector2i(1900, 768) +render_target_update_mode = 4 + +[node name="ArenaMap" parent="ViewportContainer/Viewport" instance=ExtResource("1_bvhtq")]