Hard-edge shader

This commit is contained in:
Rob Kelly 2024-07-21 14:17:35 -06:00
parent ff7950c2ad
commit 0f1ad758e8
3 changed files with 93 additions and 5 deletions

View File

@ -11,7 +11,7 @@ config_version=5
[application] [application]
config/name="Sunstation" 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") config/features=PackedStringArray("4.2", "Forward Plus")
run/max_fps=60 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) , 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

64
src/hard_edge.gdshader Normal file
View File

@ -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;
}

28
src/main.tscn Normal file
View File

@ -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")]