From 22f594f248a2dd8d4913a985030e29e72747cd5b Mon Sep 17 00:00:00 2001 From: LUCASTUCIOUS Date: Mon, 5 Aug 2024 21:35:55 +0200 Subject: [PATCH] wip: sticker flip shader --- core/stickernode.gd | 8 +- shaders/pageflip.gdshader | 121 +++++++++++++++++++++++++++++++ shaders/shaderMaterial_flip.tres | 8 ++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 shaders/pageflip.gdshader create mode 100644 shaders/shaderMaterial_flip.tres 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/shaders/pageflip.gdshader b/shaders/pageflip.gdshader new file mode 100644 index 0000000..b9b78dd --- /dev/null +++ b/shaders/pageflip.gdshader @@ -0,0 +1,121 @@ +shader_type canvas_item; +uniform vec2 scale = vec2(1,1); +uniform float flip_param = 0.0; + +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; +} + +vec4 ColorWithA(vec4 oldCol,vec4 newCol){ + vec4 finalCol; + if((newCol.a + oldCol.a)>=1.) { + 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() { + vec2 start_flip_pos = vec2(0.8, -0.2); + vec2 end_flip_pos = vec2(0, 1); + // Interpolate flip_pos based on flip_param + vec2 flip_pos = mix(start_flip_pos, end_flip_pos, flip_param); + + vec2 uv = UV; + vec4 finalColor = vec4(0.0); // Initialize with transparent color + float scale_min = scale.x/scale.y; + vec2 uv_max = vec2(scale_min,1.); + float trueScale; + if(scale.y < scale.x) { + scale_min = scale.y/scale.x; + uv.y = uv.y * scale_min; + uv_max = vec2(1.,scale_min); + trueScale = scale.x; + } else { + uv.x = uv.x * scale_min; + trueScale = scale.y; + } + + COLOR = texture(TEXTURE, uv); + + vec2 pPos = uv / TEXTURE_PIXEL_SIZE * trueScale; + if (flip_pos.x > -0.0001) { + vec2 left_bottom = vec2(0., uv_max.y / TEXTURE_PIXEL_SIZE.y * trueScale); + vec2 midpoint = (flip_pos - left_bottom) / 2. + left_bottom; + vec2 midDirect = normalize(vec2(-(flip_pos - left_bottom).y, (flip_pos - left_bottom).x)); + + vec2 sharpPoint = vec2(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 = length(flip_pos - left_bottom); + if (cyOriOff > 100.) cyOriOff = 100.; + float cyR = cyOriOff * 2. / PI; + float pageHDire = PI / 6.; + vec2 midlineToP = Line2point(midpoint, midDirect, pPos); + vec2 sideEdgeToP = Line2point(flip_pos, flipEdgeDire, pPos); + vec2 BottomEdgeToP = Line2point(flip_pos, flipEdgeDireB, pPos); + + vec2 cyOriToP = midlineToP - normalize(flip_pos - left_bottom) * cyOriOff; + vec2 cyEdgeToP = midlineToP - normalize(flip_pos - left_bottom) * (cyOriOff - cyR); + + bool atBG = (cyOriToP).x <= -0.01; + bool atPageBack = !atBG && (sideEdgeToP.y > 0.) && (BottomEdgeToP.x <= 0.); + bool atCy = cyEdgeToP.x >= 0. && (cyOriToP).x <= 0.; + bool atCyPage = false; + vec2 uvCy; + vec2 uvCyB; + + float shadow = 1.; + 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 * TEXTURE_PIXEL_SIZE / trueScale; + shadow *= 1. - pow(length(trueDis) / (cyR * PI / 2.), 3.); + + if ((BottomEdgeToTP.x < 0.) && (sideEdgeToTP.y > 0.)) { + atCyPage = true; + uvCy = vec2(length(sideEdgeToTP), left_bottom.y - length(BottomEdgeToTP)) * TEXTURE_PIXEL_SIZE / trueScale; + } + + if ((uvCyB.x > uv_max.x) || (uvCyB.y > uv_max.y) || (uvCyB.x <= 0.) || (uvCyB.y <= 0.)) + atCy = false; + } + + COLOR = vec4(0.); + 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 *= 0.8; + finalColor = mix(finalColor, cyPageColor, cyPageColor.a); + } else if (atPageBack) { + uv = vec2(length(sideEdgeToP), left_bottom.y - length(BottomEdgeToP)) * TEXTURE_PIXEL_SIZE / trueScale; + vec4 pageBackColor = texture(TEXTURE, uv); + pageBackColor.xyz *= 0.8; + finalColor = mix(finalColor, pageBackColor, pageBackColor.a); + } + + COLOR = finalColor; + } +} diff --git a/shaders/shaderMaterial_flip.tres b/shaders/shaderMaterial_flip.tres new file mode 100644 index 0000000..e262d87 --- /dev/null +++ b/shaders/shaderMaterial_flip.tres @@ -0,0 +1,8 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://583rlv8jgawy"] + +[ext_resource type="Shader" path="res://shaders/pageflip.gdshader" id="1_uvxgr"] + +[resource] +shader = ExtResource("1_uvxgr") +shader_parameter/scale = Vector2(1, 1) +shader_parameter/flip_param = 0.0