From 73e40ed127f4a43315fe56293549a24e50fd9501 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas Date: Thu, 18 Jan 2024 00:19:30 +0200 Subject: [PATCH] Add a ShaderInclude file for common shader rotation code --- .../Rotation/CommonRotation.gdshaderinc | 49 ++++++++++++++++++ .../Rotation/NearestNeighbour.gdshader | 47 ++--------------- .../Effects/Rotation/OmniScale.gdshader | 50 ++----------------- .../Effects/Rotation/cleanEdge.gdshader | 45 ++--------------- 4 files changed, 61 insertions(+), 130 deletions(-) create mode 100644 src/Shaders/Effects/Rotation/CommonRotation.gdshaderinc diff --git a/src/Shaders/Effects/Rotation/CommonRotation.gdshaderinc b/src/Shaders/Effects/Rotation/CommonRotation.gdshaderinc new file mode 100644 index 000000000..43d7dbd31 --- /dev/null +++ b/src/Shaders/Effects/Rotation/CommonRotation.gdshaderinc @@ -0,0 +1,49 @@ +uniform sampler2D selection_tex; +uniform vec2 pivot_pixel; +uniform float angle; + +vec2 rotate(vec2 uv, vec2 pivot, float ratio) { + // Scale and center image + uv.x -= pivot.x; + uv.x *= ratio; + uv.x += pivot.x; + + // Rotate image + uv -= pivot; + mat3 transformation = mat3( + vec3(cos(angle), -sin(angle), 0.0), + vec3(sin(angle), cos(angle), 0.0), + vec3(0.0, 0.0, 1.0) + ); + + uv = (transformation * vec3(uv, 1.0)).xy; + uv.x /= ratio; + uv += pivot; + + return uv; +} + +vec4 mix_rotated_and_original(vec4 color, vec4 original_color, vec2 uv, vec2 rotated_uv, vec2 tex_pixel_size) { + color.a *= texture(selection_tex, rotated_uv).a; // Combine with selection mask + // Make a border to prevent stretching pixels on the edge + vec2 border_uv = rotated_uv; + + // Center the border + border_uv -= 0.5; + border_uv *= 2.0; + border_uv = abs(border_uv); + + float border = max(border_uv.x, border_uv.y); // This is a rectangular gradient + border = floor(border - tex_pixel_size.x); // Turn the grad into a rectangle shape + border = 1.0 - clamp(border, 0.0, 1.0); // Invert the rectangle + + float selection = texture(selection_tex, uv).a; + float mask = mix(selection, 1.0, 1.0 - ceil(original_color.a)); // Combine selection mask with area outside original + + vec4 final_color; + // Combine original and rotated image only when intersecting, otherwise just pure rotated image. + final_color.rgb = mix(mix(original_color.rgb, color.rgb, color.a * border), color.rgb, mask); + final_color.a = mix(original_color.a, 0.0, selection); // Remove alpha on the selected area + final_color.a = mix(final_color.a, 1.0, color.a * border); // Combine alpha of original image and rotated + return final_color; +} \ No newline at end of file diff --git a/src/Shaders/Effects/Rotation/NearestNeighbour.gdshader b/src/Shaders/Effects/Rotation/NearestNeighbour.gdshader index 7dfbc470c..9d8564b09 100644 --- a/src/Shaders/Effects/Rotation/NearestNeighbour.gdshader +++ b/src/Shaders/Effects/Rotation/NearestNeighbour.gdshader @@ -1,56 +1,17 @@ shader_type canvas_item; render_mode unshaded; -uniform float angle; -uniform sampler2D selection_tex; -uniform vec2 pivot_pixel; - - -vec2 rotate(vec2 uv, vec2 pivot, float ratio) { - // Scale and center image - uv.x -= pivot.x; - uv.x *= ratio; - uv.x += pivot.x; - - // Rotate image - uv -= pivot; - uv = vec2(cos(angle) * uv.x + sin(angle) * uv.y, - -sin(angle) * uv.x + cos(angle) * uv.y); - uv.x /= ratio; - uv += pivot; - - return uv; -} +#include "res://src/Shaders/Effects/Rotation/CommonRotation.gdshaderinc" void fragment() { vec4 original = texture(TEXTURE, UV); - float selection = texture(selection_tex, UV).a; - vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE; // Texture size in real pixel coordinates vec2 pixelated_uv = floor(UV * tex_size) / (tex_size - 1.0); // Pixelate UV to fit resolution vec2 pivot = pivot_pixel / tex_size; // Normalize pivot position float ratio = tex_size.x / tex_size.y; // Resolution ratio - // Make a border to prevent stretching pixels on the edge - vec2 border_uv = rotate(pixelated_uv, pivot, ratio); - - // Center the border - border_uv -= 0.5; - border_uv *= 2.0; - border_uv = abs(border_uv); - - float border = max(border_uv.x, border_uv.y); // This is a rectangular gradient - border = floor(border - TEXTURE_PIXEL_SIZE.x); // Turn the grad into a rectangle shape - border = 1.0 - clamp(border, 0.0, 1.0); // Invert the rectangle - - // Mixing - vec4 rotated = texture(TEXTURE, rotate(pixelated_uv, pivot, ratio)); // Rotated image - rotated.a *= texture(selection_tex, rotate(pixelated_uv, pivot, ratio)).a; // Combine with selection mask - float mask = mix(selection, 1.0, 1.0 - ceil(original.a)); // Combine selection mask with area outside original - - // Combine original and rotated image only when intersecting, otherwise just pure rotated image. - COLOR.rgb = mix(mix(original.rgb, rotated.rgb, rotated.a * border), rotated.rgb, mask); - COLOR.a = mix(original.a, 0.0, selection); // Remove alpha on the selected area - COLOR.a = mix(COLOR.a, 1.0, rotated.a * border); // Combine alpha of original image and rotated + vec2 rotated_uv = rotate(pixelated_uv, pivot, ratio); + vec4 rotated_color = texture(TEXTURE, rotated_uv); // Rotated image + COLOR = mix_rotated_and_original(rotated_color, original, UV, rotated_uv, TEXTURE_PIXEL_SIZE); } diff --git a/src/Shaders/Effects/Rotation/OmniScale.gdshader b/src/Shaders/Effects/Rotation/OmniScale.gdshader index 3510ef97b..832fae4cb 100644 --- a/src/Shaders/Effects/Rotation/OmniScale.gdshader +++ b/src/Shaders/Effects/Rotation/OmniScale.gdshader @@ -33,6 +33,8 @@ shader_type canvas_item; // SOFTWARE. // +#include "res://src/Shaders/Effects/Rotation/CommonRotation.gdshaderinc" + uniform int ScaleMultiplier : hint_range(0, 100) = 4; // vertex compatibility #defines @@ -40,9 +42,6 @@ uniform int ScaleMultiplier : hint_range(0, 100) = 4; // #define outsize vec4(OutputSize, 1.0 / OutputSize) // Pixelorama-specific uniforms -uniform float angle; -uniform sampler2D selection_tex; -uniform vec2 pivot_pixel; uniform bool preview = false; @@ -289,27 +288,9 @@ vec4 scale(sampler2D image, vec2 coord, vec2 pxSize) { } -vec2 rotate(vec2 uv, vec2 pivot, float ratio) { // Taken from NearestNeighbour shader - // Scale and center image - uv.x -= pivot.x; - uv.x *= ratio; - uv.x += pivot.x; - - // Rotate image - uv -= pivot; - uv = vec2(cos(angle) * uv.x + sin(angle) * uv.y, - -sin(angle) * uv.x + cos(angle) * uv.y); - uv.x /= ratio; - uv += pivot; - - return uv; -} - - void fragment() { vec4 original = texture(TEXTURE, UV); - float selection = texture(selection_tex, UV).a; vec2 size = 1.0 / TEXTURE_PIXEL_SIZE; vec2 pivot = pivot_pixel / size; // Normalize pivot position float ratio = size.x / size.y; // Resolution ratio @@ -321,29 +302,8 @@ void fragment() else { rotated_uv = rotate(UV, pivot, ratio); } - vec4 c; - c = scale(TEXTURE, rotated_uv, TEXTURE_PIXEL_SIZE); + vec4 c = scale(TEXTURE, rotated_uv, TEXTURE_PIXEL_SIZE); - // Taken from NearestNeighbour shader - c.a *= texture(selection_tex, rotated_uv).a; // Combine with selection mask - // Make a border to prevent stretching pixels on the edge - vec2 border_uv = rotated_uv; - - // Center the border - border_uv -= 0.5; - border_uv *= 2.0; - border_uv = abs(border_uv); - - float border = max(border_uv.x, border_uv.y); // This is a rectangular gradient - border = floor(border - TEXTURE_PIXEL_SIZE.x); // Turn the grad into a rectangle shape - border = 1.0 - clamp(border, 0.0, 1.0); // Invert the rectangle - - float mask = mix(selection, 1.0, 1.0 - ceil(original.a)); // Combine selection mask with area outside original - - // Combine original and rotated image only when intersecting, otherwise just pure rotated image. - COLOR.rgb = mix(mix(original.rgb, c.rgb, c.a * border), c.rgb, mask); - COLOR.a = mix(original.a, 0.0, selection); // Remove alpha on the selected area - COLOR.a = mix(COLOR.a, 1.0, c.a * border); // Combine alpha of original image and rotated - //c.a = step(0.5,c.a); - //COLOR = c; + // Pixelorama edit + COLOR = mix_rotated_and_original(c, original, UV, rotated_uv, TEXTURE_PIXEL_SIZE); } \ No newline at end of file diff --git a/src/Shaders/Effects/Rotation/cleanEdge.gdshader b/src/Shaders/Effects/Rotation/cleanEdge.gdshader index 9add3d6de..38c90775a 100644 --- a/src/Shaders/Effects/Rotation/cleanEdge.gdshader +++ b/src/Shaders/Effects/Rotation/cleanEdge.gdshader @@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE. shader_type canvas_item; - +#include "res://src/Shaders/Effects/Rotation/CommonRotation.gdshaderinc" //enables 2:1 slopes. otherwise only uses 45 degree slopes #define SLOPE //cleans up small detail slope transitions (if SLOPE is enabled) @@ -45,9 +45,6 @@ uniform float similarThreshold = 0.0; uniform float lineWidth = 1.0; // Edited for Pixelorama -uniform float angle; -uniform sampler2D selection_tex; -uniform vec2 pivot_pixel; uniform bool preview = false; bool similar(vec4 col1, vec4 col2){ @@ -274,28 +271,10 @@ vec4 sliceDist(vec2 point, vec2 mainDir, vec2 pointDir, vec4 u, vec4 uf, vec4 uf return vec4(-1.0); } -// Pixelorama edit, taken from NearestNeighbour shader -vec2 rotate(vec2 uv, vec2 pivot, float ratio) { - // Scale and center image - uv.x -= pivot.x; - uv.x *= ratio; - uv.x += pivot.x; - - // Rotate image - uv -= pivot; - uv = vec2(cos(angle) * uv.x + sin(angle) * uv.y, - -sin(angle) * uv.x + cos(angle) * uv.y); - uv.x /= ratio; - uv += pivot; - - return uv; -} - void fragment() { vec2 size = 1.0/TEXTURE_PIXEL_SIZE+0.0001; //fix for some sort of rounding error // Pixelorama edit vec4 original = texture(TEXTURE, UV); - float selection = texture(selection_tex, UV).a; vec2 pivot = pivot_pixel / size; // Normalize pivot position float ratio = size.x / size.y; // Resolution ratio vec2 pixelated_uv = floor(UV * size) / (size - 1.0); // Pixelate UV to fit resolutio @@ -360,24 +339,6 @@ void fragment() { col = u_col; } - // Pixelorama edit, taken from NearestNeighbour shader - col.a *= texture(selection_tex, rotated_uv).a; // Combine with selection mask - // Make a border to prevent stretching pixels on the edge - vec2 border_uv = rotated_uv; - - // Center the border - border_uv -= 0.5; - border_uv *= 2.0; - border_uv = abs(border_uv); - - float border = max(border_uv.x, border_uv.y); // This is a rectangular gradient - border = floor(border - TEXTURE_PIXEL_SIZE.x); // Turn the grad into a rectangle shape - border = 1.0 - clamp(border, 0.0, 1.0); // Invert the rectangle - - float mask = mix(selection, 1.0, 1.0 - ceil(original.a)); // Combine selection mask with area outside original - - // Combine original and rotated image only when intersecting, otherwise just pure rotated image. - COLOR.rgb = mix(mix(original.rgb, col.rgb, col.a * border), col.rgb, mask); - COLOR.a = mix(original.a, 0.0, selection); // Remove alpha on the selected area - COLOR.a = mix(COLOR.a, 1.0, col.a * border); // Combine alpha of original image and rotated + // Pixelorama edit + COLOR = mix_rotated_and_original(col, original, UV, rotated_uv, TEXTURE_PIXEL_SIZE); }