Added retro postprocessing shader for later use

This commit is contained in:
Rob Kelly 2024-11-13 00:17:08 -07:00
parent 6ad1ce2140
commit 1bd11434e4
6 changed files with 365 additions and 2 deletions

View File

@ -177,6 +177,7 @@ camera_attributes = SubResource("CameraAttributesPractical_ypy22")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(0.782608, -0.611691, 0.11558, 0, 0.185667, 0.982613, -0.622515, -0.769001, 0.145304, 0, 0, 0)
shadow_enabled = true
shadow_blur = 4.0
[node name="Buildings" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 129.404, -9.53674e-07, 309.4)

View File

@ -161,5 +161,4 @@ jolt_3d/limits/max_temporary_memory=64
textures/canvas_textures/default_texture_filter=0
anti_aliasing/quality/msaa_3d=3
anti_aliasing/quality/screen_space_aa=1
anti_aliasing/quality/use_taa=true
anti_aliasing/quality/use_debanding=true

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=40 format=3 uid="uid://cy7t2tc4y3b4"]
[gd_scene load_steps=42 format=3 uid="uid://cy7t2tc4y3b4"]
[ext_resource type="Script" path="res://src/player/shot_setup/shot_setup.gd" id="1_r6ei4"]
[ext_resource type="PackedScene" uid="uid://dfttci386ohip" path="res://src/player/physics_ball/physics_ball.tscn" id="2_1i5j5"]
@ -7,6 +7,7 @@
[ext_resource type="PackedScene" uid="uid://445qd7m4qe2j" path="res://src/player/shot_setup/club_selector/club_selector.tscn" id="4_56ape"]
[ext_resource type="PackedScene" uid="uid://fht6j87o8ecr" path="res://src/ui/projectile_arc/projectile_arc.tscn" id="4_ry2ho"]
[ext_resource type="PackedScene" uid="uid://dbdul15c4oblg" path="res://src/ui/projected_target.tscn" id="6_mynqj"]
[ext_resource type="Shader" path="res://src/shaders/canvas_retro.gdshader" id="7_h6c4m"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_lnol1"]
albedo_color = Color(0, 0.537255, 1, 1)
@ -480,6 +481,15 @@ _data = {
"display": SubResource("Animation_g52q7")
}
[sub_resource type="ShaderMaterial" id="ShaderMaterial_afsun"]
shader = ExtResource("7_h6c4m")
shader_parameter/change_color_depth = true
shader_parameter/target_color_depth = 6
shader_parameter/dithering = true
shader_parameter/scale_resolution = true
shader_parameter/target_resolution_scale = 2
shader_parameter/enable_recolor = false
[sub_resource type="Animation" id="Animation_pk1s7"]
length = 0.001
tracks/0/type = "bezier"
@ -852,6 +862,17 @@ libraries = {
"": SubResource("AnimationLibrary_gbnnr")
}
[node name="ColorRect" type="ColorRect" parent="ShotUI"]
visible = false
material = SubResource("ShaderMaterial_afsun")
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[node name="ShotGauges" type="Control" parent="ShotUI"]
layout_mode = 1
anchor_left = 0.4

View File

@ -0,0 +1,168 @@
// CanvasItem Retro Post-processing
// Adapted from https://godotshaders.com/shader/retro-post-processing/
shader_type canvas_item;
// Handles the resolution changes, color depth, and dithering
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
group_uniforms resolution_and_colors;
uniform bool change_color_depth = false;
uniform int target_color_depth : hint_range(1, 8) = 5;
uniform bool dithering = false;
uniform bool scale_resolution = false;
uniform int target_resolution_scale = 3;
// Handles the LUTish recoloring
group_uniforms gradient_recoloring;
uniform bool enable_recolor = false;
uniform sampler2D to_gradient: hint_default_black;
int dithering_pattern(ivec2 fragcoord) {
const int pattern[] = {
-4, +0, -3, +1,
+2, -2, +3, -1,
-3, +1, -4, +0,
+3, -1, +2, -2
};
int x = fragcoord.x % 4;
int y = fragcoord.y % 4;
return pattern[y * 4 + x];
}
vec3 rgb2hsv(vec3 rgb) { //Converts RGB values to HSV
float r = rgb.r;
float g = rgb.g;
float b = rgb.b;
float cmax = max(r,max(g,b));
float cmin = min(r,min(g,b));
float delta = cmax - cmin;
float h = 0.f; //hue
if (delta > 0.f){
if (cmax == r){
h = (g-b)/delta;
h = mod(h,6.f);
} else if (cmax == g){
h = ((b - r) / delta) + 2.f;
} else {
h = ((r-g)/delta) + 4.f;
}
h = h * 60.f;
}
float s = 0.f; //saturation
if (cmax > 0.f){
s = delta / cmax;
}
return vec3(h,s,cmax); // Keep original alpha value
}
vec3 hsv2rgb(vec3 hsv) { //Converts HSV values to RGB
float h = hsv.r;
float s = hsv.g;
float v = hsv.b;
float c = v * s;
//X = C × (1 - |(H / 60°) mod 2 - 1|)
float x = h / 60.f;
x = mod(x,2.f);
x = abs(x - 1.f);
x = c * (1.f - x);
float m = v - c;
vec3 rgb = vec3(0.f,0.f,0.f);
if (h < 60.f) {
rgb = vec3(c,x,0.f);
} else if (h < 120.f){
rgb = vec3(x,c,0.f);
} else if (h < 180.f){
rgb = vec3(0.f,c,x);
} else if (h < 240.f){
rgb = vec3(0.f,x,c);
} else if (h < 300.f){
rgb = vec3(x,0.f,c);
} else if (h < 360.f){
rgb = vec3(c,0.f,x);
}
rgb[0] = rgb[0] + m;
rgb[1] = rgb[1] + m;
rgb[2] = rgb[2] + m;
return rgb;
}
void fragment() {
vec2 iResolution = 1.0 / SCREEN_PIXEL_SIZE;
vec2 q = FRAGCOORD.xy / iResolution.xy;
ivec2 uv = ivec2(q);
vec3 color = texture(screen_texture, vec2(q.x,q.y) ).xyz;
if(scale_resolution){
uv = ivec2(FRAGCOORD.xy / float(target_resolution_scale));
color = texelFetch(screen_texture, uv * target_resolution_scale, 0).rgb;
} else {
uv = ivec2(FRAGCOORD.xy);
color = texelFetch(screen_texture, uv, 0).rgb;
}
if(enable_recolor){
vec3 hsv = rgb2hsv(color);
float color_pos = (hsv.x / 360.0);
vec3 new_color = texture(to_gradient, vec2((color_pos), 0.5)).rgb;
vec3 new_hsv = rgb2hsv(new_color);
hsv.x = new_hsv.x;
vec3 final_rgb = hsv2rgb(hsv);
color.rgb = final_rgb;
}
// Convert from [0.0, 1.0] range to [0, 255] range
ivec3 c = ivec3(round(color * 255.0));
// Apply the dithering pattern
if (dithering) {
c += ivec3(dithering_pattern(uv));
}
vec3 final_color;
if(change_color_depth){
// Truncate from 8 bits to color_depth bits
c >>= (8 - target_color_depth);
final_color = vec3(c) / float(1 << target_color_depth);
} else {
final_color = vec3(c) / float(1 << 8);
}
// Convert back to [0.0, 1.0] range
COLOR.rgb = final_color;
}

View File

@ -0,0 +1,143 @@
// Retro Post-Processing shader
// From https://godotshaders.com/shader/retro-post-processing/
shader_type canvas_item;
// Handles the resolution changes, color depth, and dithering
group_uniforms resolution_and_colors;
uniform bool change_color_depth = false;
uniform int target_color_depth : hint_range(1, 8) = 5;
uniform bool dithering = false;
uniform bool scale_resolution = false;
uniform int target_resolution_scale = 3;
// Handles the LUTish recoloring
group_uniforms gradient_recoloring;
uniform bool enable_recolor = false;
uniform sampler2D to_gradient: hint_default_black;
int dithering_pattern(ivec2 fragcoord) {
const int pattern[] = {
-4, +0, -3, +1,
+2, -2, +3, -1,
-3, +1, -4, +0,
+3, -1, +2, -2
};
int x = fragcoord.x % 4;
int y = fragcoord.y % 4;
return pattern[y * 4 + x];
}
vec3 rgb2hsv(vec3 rgb) { //Converts RGB values to HSV
float r = rgb.r;
float g = rgb.g;
float b = rgb.b;
float cmax = max(r,max(g,b));
float cmin = min(r,min(g,b));
float delta = cmax - cmin;
float h = 0.f; //hue
if (delta > 0.f){
if (cmax == r){
h = (g-b)/delta;
h = mod(h,6.f);
} else if (cmax == g){
h = ((b - r) / delta) + 2.f;
} else {
h = ((r-g)/delta) + 4.f;
}
h = h * 60.f;
}
float s = 0.f; //saturation
if (cmax > 0.f){
s = delta / cmax;
}
return vec3(h,s,cmax); // Keep original alpha value
}
vec3 hsv2rgb(vec3 hsv) { //Converts HSV values to RGB
float h = hsv.r;
float s = hsv.g;
float v = hsv.b;
float c = v * s;
//X = C × (1 - |(H / 60°) mod 2 - 1|)
float x = h / 60.f;
x = mod(x,2.f);
x = abs(x - 1.f);
x = c * (1.f - x);
float m = v - c;
vec3 rgb = vec3(0.f,0.f,0.f);
if (h < 60.f) {
rgb = vec3(c,x,0.f);
} else if (h < 120.f){
rgb = vec3(x,c,0.f);
} else if (h < 180.f){
rgb = vec3(0.f,c,x);
} else if (h < 240.f){
rgb = vec3(0.f,x,c);
} else if (h < 300.f){
rgb = vec3(x,0.f,c);
} else if (h < 360.f){
rgb = vec3(c,0.f,x);
}
rgb[0] = rgb[0] + m;
rgb[1] = rgb[1] + m;
rgb[2] = rgb[2] + m;
return rgb;
}
void fragment() {
ivec2 uv;
vec3 color;
if(scale_resolution){
uv = ivec2(FRAGCOORD.xy / float(target_resolution_scale));
color = texelFetch(TEXTURE, uv * target_resolution_scale, 0).rgb;
} else {
uv = ivec2(FRAGCOORD.xy);
color = texelFetch(TEXTURE, uv, 0).rgb;
}
if(enable_recolor){
vec3 hsv = rgb2hsv(color);
float color_pos = (hsv.x / 360.0);
vec3 new_color = texture(to_gradient, vec2((color_pos), 0.5)).rgb;
vec3 new_hsv = rgb2hsv(new_color);
hsv.x = new_hsv.x;
vec3 final_rgb = hsv2rgb(hsv);
color.rgb = final_rgb;
}
// Convert from [0.0, 1.0] range to [0, 255] range
ivec3 c = ivec3(round(color * 255.0));
// Apply the dithering pattern
if (dithering) {
c += ivec3(dithering_pattern(uv));
}
vec3 final_color;
if(change_color_depth){
// Truncate from 8 bits to color_depth bits
c >>= (8 - target_color_depth);
final_color = vec3(c) / float(1 << target_color_depth);
} else {
final_color = vec3(c) / float(1 << 8);
}
// Convert back to [0.0, 1.0] range
COLOR.rgb = final_color;
}

31
src/world/world.tscn Normal file
View File

@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=3 uid="uid://cwnwcd8kushl3"]
[ext_resource type="Shader" path="res://src/shaders/retro_postprocessing.gdshader" id="1_3gv54"]
[ext_resource type="PackedScene" uid="uid://bm2o3mex10v11" path="res://levels/debug_level/debug_level.tscn" id="1_pge3b"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_sc4r2"]
shader = ExtResource("1_3gv54")
shader_parameter/change_color_depth = true
shader_parameter/target_color_depth = 8
shader_parameter/dithering = true
shader_parameter/scale_resolution = true
shader_parameter/target_resolution_scale = 3
shader_parameter/enable_recolor = false
[node name="World" type="Node"]
[node name="SubViewportContainer" type="SubViewportContainer" parent="."]
material = SubResource("ShaderMaterial_sc4r2")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
stretch = true
[node name="SubViewport" type="SubViewport" parent="SubViewportContainer"]
size = Vector2i(1280, 720)
[node name="Level" type="Node3D" parent="SubViewportContainer/SubViewport"]
[node name="TestLevel" parent="SubViewportContainer/SubViewport/Level" instance=ExtResource("1_pge3b")]