From 6d4094bfeef94717ab116013e7dc9f8c88e0b764 Mon Sep 17 00:00:00 2001 From: LUCASTUCIOUS Date: Mon, 5 Aug 2024 21:35:55 +0200 Subject: [PATCH 1/2] sticker flip shader Need to add the outline shader --- core/stickernode.gd | 8 +- developers/lucas/flip shader gym.tscn | 12 +++ shaders/pageflip2.gdshader | 126 ++++++++++++++++++++++++++ shaders/shaderMaterial_flip.tres | 10 ++ shaders/shader_outline.gdshader | 53 ----------- 5 files changed, 154 insertions(+), 55 deletions(-) create mode 100644 developers/lucas/flip shader gym.tscn create mode 100644 shaders/pageflip2.gdshader create mode 100644 shaders/shaderMaterial_flip.tres delete mode 100644 shaders/shader_outline.gdshader diff --git a/core/stickernode.gd b/core/stickernode.gd index 34ba61f..583915e 100644 --- a/core/stickernode.gd +++ b/core/stickernode.gd @@ -38,6 +38,8 @@ var detected_solids:Array var detected_zones:Array var Grabbed:bool = false +## Emitted when the sticker overlap a blocking body, preventing to be spawned as an asset in the level. Usually received by the cursor to change his sprite +signal spawn_mode_changed(can_spawn:bool) #region Functions func _get_configuration_warnings(): if (get_parent() == get_tree().get_edited_scene_root()): @@ -75,17 +77,19 @@ func _ready(): area_exited.connect(_on_area_exited) body_entered.connect(_on_body_entered) body_exited.connect(_on_body_exited) + # TODO : Solids and interactive zone detection area should not be the same as the sticker area. # IDEA: Need to export a child Area2D func _on_body_entered(body:Node2D): print("body entered",body) detected_solids.append(body) + spawn_mode_changed.emit(false) func _on_body_exited(body:Node2D): print("body exited",body) detected_solids.erase(body) - if(Sticker_mode and Grabbed and detected_solids.size() == 0): - print("Can be released in object mode") + if(Sticker_mode and Grabbed and detected_solids.size() == 0 ): + spawn_mode_changed.emit(true) func _on_area_entered(area:Area2D): print("area entered",area) #TODO:Filter by type diff --git a/developers/lucas/flip shader gym.tscn b/developers/lucas/flip shader gym.tscn new file mode 100644 index 0000000..be44957 --- /dev/null +++ b/developers/lucas/flip shader gym.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=3 format=3 uid="uid://cww6s8uqhlws1"] + +[ext_resource type="Material" uid="uid://583rlv8jgawy" path="res://shaders/shaderMaterial_flip.tres" id="1_k0ogt"] +[ext_resource type="Texture2D" uid="uid://dggavne4ueche" path="res://textures/sprites/Tree_Field_01_SPRT.png" id="2_gtigr"] + +[node name="Node2D" type="Node2D"] + +[node name="Sprite2D" type="Sprite2D" parent="."] +material = ExtResource("1_k0ogt") +position = Vector2(-8261, 513) +scale = Vector2(71.2109, 48.0078) +texture = ExtResource("2_gtigr") diff --git a/shaders/pageflip2.gdshader b/shaders/pageflip2.gdshader new file mode 100644 index 0000000..b3298db --- /dev/null +++ b/shaders/pageflip2.gdshader @@ -0,0 +1,126 @@ +shader_type canvas_item; + +uniform float flip_param : hint_range(0.0, 1.0); // Parameter to control the flipping effect +uniform float dim_color_scale : hint_range(0.0, 1.0) = 0.4; // Control the dim of the back of the flipped texture + +uniform float x_buffer = 2.0;//Increase these if you need your flip to stretch further +uniform float y_buffer = 2.0; + +const vec2 scale = vec2(1, 1); // Scale of the texture +const vec2 start_flip_pos = vec2(1.0, 0.0); // Starting position of the flip +const vec2 end_flip_pos = vec2(0, 1); // Ending position of the flip + +// Function to calculate the vector from a line to a point +vec2 Line2point(vec2 linePoint, vec2 lineDire, vec2 point) { + lineDire = normalize(lineDire); // Normalize the direction of the line + return -linePoint - dot(-linePoint, lineDire) * lineDire - (-point - dot(-point, lineDire) * lineDire); +} + + +void vertex() { + //This increases the size of the uv so the sprite can be drawn 'out of bounds' + VERTEX.x *= x_buffer; + VERTEX.y *= y_buffer; +} + +// Main fragment shader function +void fragment() { + + // Resize the texture coordinates before the buffer + vec2 uv = vec2((UV.x - 0.5) * x_buffer + 0.5, (UV.y - 0.5) * y_buffer + 0.5); + + // Interpolate flip position based on flip_param + vec2 flip_pos = mix(start_flip_pos, end_flip_pos, flip_param); + + // Get the UV coordinates of the fragment + vec4 finalColor = vec4(0.0); // Initialize final color with transparent + float scale_min = scale.x / scale.y; + vec2 uv_max = vec2(scale_min, 1.0); + float trueScale; + + // Adjust UV coordinates based on the scale + if (scale.y < scale.x) { + scale_min = scale.y / scale.x; + uv.y *= scale_min; + uv_max = vec2(1.0, scale_min); + trueScale = scale.x; + } else { + uv.x *= scale_min; + trueScale = scale.y; + } + + // Sample the color from the texture at the given UV coordinates + COLOR = texture(TEXTURE, uv); + + // Calculate the position in texture space + vec2 pPos = uv / trueScale; + + // If the flip position is valid, can't be 0 + if (flip_pos.x > -0.00001) { + vec2 left_bottom = vec2(0.0, uv_max.y / trueScale); + vec2 midpoint = (flip_pos - left_bottom) / 2.5 + left_bottom; + vec2 midDirect = normalize(vec2(-(flip_pos - left_bottom).y, (flip_pos - left_bottom).x)); + + // Calculate sharp point and direction vectors + vec2 sharpPoint = vec2(0.0, midpoint.y - midDirect.y / midDirect.x * midpoint.x); + vec2 flipEdgeDire = normalize(sharpPoint - flip_pos); + + vec2 sharpPointB = vec2(midpoint.x - midDirect.x / midDirect.y * (midpoint - left_bottom).y, left_bottom.y); + vec2 flipEdgeDireB = normalize(sharpPointB - flip_pos); + + float cyOriOff = min(length(flip_pos - left_bottom), 100.0); + float cyR = cyOriOff * 2.05 / PI; + + vec2 midlineToP = Line2point(midpoint, midDirect, pPos); + + vec2 cyOriToP = midlineToP - normalize(flip_pos - left_bottom) * cyOriOff; + vec2 cyEdgeToP = midlineToP - normalize(flip_pos - left_bottom) * (cyOriOff - cyR); + + // Determine the location of the fragment relative to the flip + bool atBG = (cyOriToP.x <= -0.001); + bool atCy = (cyEdgeToP.x >= 0.0) && (cyOriToP.x <= 0.0); + bool atCyPage = false; + vec2 uvCy; + vec2 uvCyB; + + // If the fragment is within the curvature area + if (atCy) { + vec2 cyOri = pPos - cyOriToP; + vec2 trueDis = cyR * asin(length(cyOriToP) / cyR) * normalize(cyOriToP); + vec2 truePos = cyOri + trueDis; + + vec2 sideEdgeToTP = Line2point(flip_pos, flipEdgeDire, truePos); + vec2 BottomEdgeToTP = Line2point(flip_pos, flipEdgeDireB, truePos); + uvCyB = truePos * trueScale; + + if ((BottomEdgeToTP.x < 0.0) && (sideEdgeToTP.y > 0.0)) { + atCyPage = true; + uvCy = vec2(length(sideEdgeToTP), left_bottom.y - length(BottomEdgeToTP)) * trueScale; + } + + if ((uvCyB.x > uv_max.x) || (uvCyB.y > uv_max.y) || (uvCyB.x <= 0.0) || (uvCyB.y <= 0.0)) { + atCy = false; + } + } + + // If the fragment is not within the background or curvature area, sample the color from the texture + if (!atBG && !atCy) { + finalColor = texture(TEXTURE, uv); + } + + // If the fragment is within the curvature area, sample the color with curvature effect + if (atCy) { + finalColor = texture(TEXTURE, uvCyB); + } + + // If the fragment is on the flipped page, adjust the color for the back of the page + if (atCyPage) { + vec4 cyPageColor = texture(TEXTURE, uvCy); + cyPageColor.rgb *= dim_color_scale; // Dim the color slightly + finalColor = mix(finalColor, cyPageColor, cyPageColor.a); + } + + // Set the final color + COLOR = finalColor; + } +} diff --git a/shaders/shaderMaterial_flip.tres b/shaders/shaderMaterial_flip.tres new file mode 100644 index 0000000..1bba997 --- /dev/null +++ b/shaders/shaderMaterial_flip.tres @@ -0,0 +1,10 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://583rlv8jgawy"] + +[ext_resource type="Shader" path="res://shaders/pageflip2.gdshader" id="1_1kmqt"] + +[resource] +shader = ExtResource("1_1kmqt") +shader_parameter/flip_param = 1.0 +shader_parameter/dim_color_scale = 0.4 +shader_parameter/x_buffer = 2.0 +shader_parameter/y_buffer = 2.0 diff --git a/shaders/shader_outline.gdshader b/shaders/shader_outline.gdshader deleted file mode 100644 index 5372eca..0000000 --- a/shaders/shader_outline.gdshader +++ /dev/null @@ -1,53 +0,0 @@ -shader_type canvas_item; - -uniform vec4 line_color : source_color = vec4(1); -uniform float line_thickness : hint_range(0, 20) = 0.0; -uniform bool add_margins = true; - -void vertex() { - if (add_margins) { - VERTEX += (UV * 2.0 - 1.0) * line_thickness; - } -} - -void fragment() { - vec2 uv = UV; - - if (add_margins) { - vec2 texture_pixel_size = vec2(1.0) / (vec2(1.0) / TEXTURE_PIXEL_SIZE + vec2(line_thickness * 2.0)); - - uv = (uv - texture_pixel_size * line_thickness) * TEXTURE_PIXEL_SIZE / texture_pixel_size; - - if (uv != clamp(uv, vec2(0.0), vec2(1.0))) { - COLOR.a = 0.0; - } else { - COLOR = texture(TEXTURE, uv); - } - } else { - COLOR = texture(TEXTURE, uv); - } - - vec2 size = TEXTURE_PIXEL_SIZE * line_thickness; - - if (line_thickness < 0.1) { - vec4 color = texture(TEXTURE, uv); - COLOR = color; - } else { - float outline = texture(TEXTURE, uv + vec2(-size.x, 0)).a; - outline += texture(TEXTURE, uv + vec2(0, size.y)).a; - outline += texture(TEXTURE, uv + vec2(size.x, 0)).a; - outline += texture(TEXTURE, uv + vec2(0, -size.y)).a; - outline += texture(TEXTURE, uv + vec2(-size.x * 0.866, size.y * 0.5)).a; - outline += texture(TEXTURE, uv + vec2(-size.x * 0.5, size.y * 0.866)).a; - outline += texture(TEXTURE, uv + vec2(size.x * 0.866, size.y * 0.5)).a; - outline += texture(TEXTURE, uv + vec2(size.x * 0.5, size.y * 0.866)).a; - outline += texture(TEXTURE, uv + vec2(-size.x * 0.866, -size.y * 0.5)).a; - outline += texture(TEXTURE, uv + vec2(-size.x * 0.5, -size.y * 0.866)).a; - outline += texture(TEXTURE, uv + vec2(size.x * 0.866, -size.y * 0.5)).a; - outline += texture(TEXTURE, uv + vec2(size.x * 0.5, -size.y * 0.866)).a; - outline = min(outline, 1.0); - - vec4 color = texture(TEXTURE, uv); - COLOR = mix(color, line_color, outline - color.a); - } -} \ No newline at end of file -- 2.20.1 From a2345a52380da551581f9b8e7c5e34b8cd1b9d9d Mon Sep 17 00:00:00 2001 From: Lucas Peter Date: Mon, 10 Feb 2025 19:04:27 +0100 Subject: [PATCH 2/2] update working flip shader --- shaders/pageflip2.gdshader | 6 ++ shaders/pageflip2.gdshader.uid | 1 + shaders/pageflipweb.gdshader | 145 +++++++++++++++++++++++++++++++ shaders/pageflipweb.gdshader.uid | 1 + shaders/pageflipweb.tres | 12 +++ 5 files changed, 165 insertions(+) create mode 100644 shaders/pageflip2.gdshader.uid create mode 100644 shaders/pageflipweb.gdshader create mode 100644 shaders/pageflipweb.gdshader.uid create mode 100644 shaders/pageflipweb.tres diff --git a/shaders/pageflip2.gdshader b/shaders/pageflip2.gdshader index b3298db..7e8f032 100644 --- a/shaders/pageflip2.gdshader +++ b/shaders/pageflip2.gdshader @@ -10,6 +10,11 @@ const vec2 scale = vec2(1, 1); // Scale of the texture const vec2 start_flip_pos = vec2(1.0, 0.0); // Starting position of the flip const vec2 end_flip_pos = vec2(0, 1); // Ending position of the flip +uniform vec2 atlas_offset = vec2(0.0); // Offset dans l'atlas +uniform vec2 atlas_size = vec2(1.0); // Taille de la région dans l'atlas + + + // Function to calculate the vector from a line to a point vec2 Line2point(vec2 linePoint, vec2 lineDire, vec2 point) { lineDire = normalize(lineDire); // Normalize the direction of the line @@ -28,6 +33,7 @@ void fragment() { // Resize the texture coordinates before the buffer vec2 uv = vec2((UV.x - 0.5) * x_buffer + 0.5, (UV.y - 0.5) * y_buffer + 0.5); + uv = UV * atlas_size + atlas_offset; // Interpolate flip position based on flip_param vec2 flip_pos = mix(start_flip_pos, end_flip_pos, flip_param); diff --git a/shaders/pageflip2.gdshader.uid b/shaders/pageflip2.gdshader.uid new file mode 100644 index 0000000..01d21ff --- /dev/null +++ b/shaders/pageflip2.gdshader.uid @@ -0,0 +1 @@ +uid://5gsjq7w5fcou diff --git a/shaders/pageflipweb.gdshader b/shaders/pageflipweb.gdshader new file mode 100644 index 0000000..bb0a766 --- /dev/null +++ b/shaders/pageflipweb.gdshader @@ -0,0 +1,145 @@ +shader_type canvas_item; + +// Scale and mouse position as input parameters +const vec2 scale = vec2(1, 1); + +uniform float dim_color_scale : hint_range(0.0, 1.0) = 0.5; +uniform float pos_x : hint_range(0.0, 1.0) = 0.0001 ; +uniform float pos_y : hint_range(0.0, 1.0) = 0.05; + +// Helper function to calculate the distance between a point and a line +vec2 Line2point(vec2 linePoint, vec2 lineDire, vec2 point) { + lineDire = normalize(lineDire); + vec2 line2Ori = -linePoint - dot(-linePoint, lineDire) * lineDire; + vec2 p2Ori = -point - dot(-point, lineDire) * lineDire; + return line2Ori - p2Ori; +} + +// Function to blend two colors based on their alpha values +vec4 ColorWithA(vec4 oldCol, vec4 newCol) { + vec4 finalCol; + if ((newCol.a + oldCol.a) >= 1.0) { + finalCol.rgb = newCol.rgb; + finalCol.a = 1.0; + } else { + finalCol.rgb = newCol.a / (newCol.a + oldCol.a) * newCol.rgb + oldCol.a / (newCol.a + oldCol.a) * oldCol.rgb; + finalCol.a = oldCol.a + newCol.a; + } + return finalCol; +} + +void fragment() { + // Initialize mouse position and final color + vec2 mouse_pos = vec2(-1., -1.); + vec2 uv = UV; + vec4 finalColor = vec4(0.0); // Transparent color initially + + // Adjust scale to maintain aspect ratio of the sprite + float scale_min = scale.x / scale.y; + vec2 uv_max = vec2(scale_min, 1.0); + float trueScale; + + if (scale.y < scale.x) { + scale_min = scale.y / scale.x; + uv.y = uv.y * scale_min; + uv_max = vec2(1.0, scale_min); + trueScale = scale.x; + } else { + uv.x = uv.x * scale_min; + trueScale = scale.y; + } + + // Normalize mouse position based on the texture pixel size + mouse_pos.x = pos_x * (1.0 / TEXTURE_PIXEL_SIZE.x); + mouse_pos.y = pos_y * (1.0 / TEXTURE_PIXEL_SIZE.y); + vec2 normalized_mouse = mouse_pos * uv_max; + + // Default texture color assignment + COLOR = texture(TEXTURE, uv); + + // Calculate sprite's position relative to the mouse + vec2 pPos = uv / TEXTURE_PIXEL_SIZE * trueScale; + + // Only process if the mouse position is valid + if (normalized_mouse.x > -0.0001) { + vec2 left_bottom = vec2(0.0, uv_max.y / TEXTURE_PIXEL_SIZE.y * trueScale); + vec2 midpoint = (normalized_mouse - left_bottom) / 2.0 + left_bottom; + vec2 midDirect = normalize(vec2(-(normalized_mouse - left_bottom).y, (normalized_mouse - left_bottom).x)); + + // Calculate flip interactions + vec2 sharpPoint = vec2(0.0, midpoint.y - midDirect.y / midDirect.x * midpoint.x); + vec2 flipEdgeDire = normalize(sharpPoint - normalized_mouse); + + vec2 sharpPointB = vec2(midpoint.x - midDirect.x / midDirect.y * (midpoint - left_bottom).y, left_bottom.y); + vec2 flipEdgeDireB = normalize(sharpPointB - normalized_mouse); + + // Flip logic based on mouse distance and angle + float cyOriOff = length(normalized_mouse - left_bottom); + if (cyOriOff > 100.0) cyOriOff = 100.0; + float cyR = cyOriOff * 2.0 / PI; + + vec2 midlineToP = Line2point(midpoint, midDirect, pPos); + vec2 sideEdgeToP = Line2point(normalized_mouse, flipEdgeDire, pPos); + vec2 BottomEdgeToP = Line2point(normalized_mouse, flipEdgeDireB, pPos); + + vec2 cyOriToP = midlineToP - normalize(normalized_mouse - left_bottom) * cyOriOff; + vec2 cyEdgeToP = midlineToP - normalize(normalized_mouse - left_bottom) * (cyOriOff - cyR); + + bool atBG = (cyOriToP).x <= -0.01; + bool atPageBack = !atBG && (sideEdgeToP.y > 0.0) && (BottomEdgeToP.x <= 0.0); + bool atCy = cyEdgeToP.x >= 0.0 && (cyOriToP).x <= 0.0; + bool atCyPage = false; + + float shadow = 1.0; + vec2 uvCy, uvCyB; + + // Handle flip state and apply shadow effect + if (atCy) { + vec2 cyOri = pPos - cyOriToP; + vec2 trueDis = cyR * asin(length(cyOriToP) / cyR) * normalize(cyOriToP); + vec2 truePos = cyOri + trueDis; + + uvCyB = truePos * TEXTURE_PIXEL_SIZE / trueScale; + shadow *= 1.0 - pow(length(trueDis) / (cyR * PI / 2.0), 3.0); + + // Determine if we are on the flip side of the page + if ((BottomEdgeToP.x < 0.0) && (sideEdgeToP.y > 0.0)) { + atCyPage = true; + uvCy = vec2(length(sideEdgeToP), left_bottom.y - length(BottomEdgeToP)) * TEXTURE_PIXEL_SIZE / trueScale; + } + + if (uvCyB.x > uv_max.x || uvCyB.y > uv_max.y || uvCyB.x <= 0.0 || uvCyB.y <= 0.0) { + atCy = false; + } + } + + // Blend final color based on conditions + COLOR = vec4(0.0); // Reset COLOR + + if (!atBG && !atCy) { + vec4 color = texture(TEXTURE, uv); + finalColor = color; + } + + if (atCy) { + vec4 cyColor = texture(TEXTURE, uvCyB); + finalColor = cyColor; + } + + if (atCyPage) { + vec4 cyPageColor = texture(TEXTURE, uvCy); + cyPageColor.xyz *= dim_color_scale; // Dim the color slightly + finalColor = mix(finalColor, cyPageColor, cyPageColor.a); + } else if (atPageBack) { // If the fragment is on the flipped page, adjust the color for the back of the page + uv = vec2(length(sideEdgeToP), left_bottom.y - length(BottomEdgeToP)) * TEXTURE_PIXEL_SIZE / trueScale; + vec4 pageBackColor = texture(TEXTURE, uv); + pageBackColor.xyz *= dim_color_scale; // Dim the back page color + finalColor = mix(finalColor, pageBackColor, pageBackColor.a); + } + + COLOR = finalColor; + } + else{ + + } +} diff --git a/shaders/pageflipweb.gdshader.uid b/shaders/pageflipweb.gdshader.uid new file mode 100644 index 0000000..0bbf103 --- /dev/null +++ b/shaders/pageflipweb.gdshader.uid @@ -0,0 +1 @@ +uid://bfbb27u1p782f diff --git a/shaders/pageflipweb.tres b/shaders/pageflipweb.tres new file mode 100644 index 0000000..1398e9b --- /dev/null +++ b/shaders/pageflipweb.tres @@ -0,0 +1,12 @@ +[gd_resource type="VisualShader" format=3 uid="uid://bxy88pmtcbiq6"] + +[resource] +code = "shader_type canvas_item; +render_mode blend_mix; + + + +" +graph_offset = Vector2(-44.3781, -104.923) +mode = 1 +flags/light_only = false -- 2.20.1