1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Add a ShaderInclude file for common shader rotation code

This commit is contained in:
Emmanouil Papadeas 2024-01-18 00:19:30 +02:00
parent aa77dcb61f
commit 73e40ed127
4 changed files with 61 additions and 130 deletions

View file

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

View file

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

View file

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

View file

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