1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-13 09:13:07 +00:00

Unify the two gradient shaders into one

This commit is contained in:
Emmanouil Papadeas 2025-02-10 20:51:06 +02:00
parent 5df01a9170
commit 93bbdb7c7b
3 changed files with 42 additions and 103 deletions

View file

@ -2,14 +2,21 @@ shader_type canvas_item;
render_mode unshaded; render_mode unshaded;
uniform sampler2D selection : filter_nearest; uniform sampler2D selection : filter_nearest;
// The gradient texture itself, with interpolation.
uniform sampler2D gradient_texture : filter_nearest; uniform sampler2D gradient_texture : filter_nearest;
// A Nx1 image, where N is the amount of the different colors of gradient_texture,
// without interpolating between them. Used in dithering.
uniform sampler2D gradient_texture_no_interpolation : filter_nearest;
// A Nx1 grayscale image, where N is the amount of the different colors of gradient_texture,
// where each pixel contains the offset, ranging from 0-1 of each color. Used in dithering.
uniform sampler2D gradient_offset_texture : filter_nearest;
uniform sampler2D dither_texture : filter_nearest, repeat_enable; uniform sampler2D dither_texture : filter_nearest, repeat_enable;
uniform sampler2D offset_texture : filter_nearest;
uniform float position : hint_range(-0.5, 0.5) = 0.0; uniform float position : hint_range(-0.5, 0.5) = 0.0;
uniform float size : hint_range(0.01, 2.0) = 1.0; uniform float size : hint_range(0.01, 2.0) = 1.0;
uniform float angle : hint_range(0.0, 360.0) = 0.0; uniform float angle : hint_range(0.0, 360.0) = 0.0;
uniform vec2 center = vec2(0.5); uniform vec2 center = vec2(0.5);
uniform vec2 radius = vec2(1.0); uniform vec2 radius = vec2(1.0);
uniform bool use_dithering = false;
uniform int shape = 0; // 0 = linear, 1 = radial uniform int shape = 0; // 0 = linear, 1 = radial
uniform int repeat = 0; // 0 = none, 1 = repeat, 2 = mirrored, 3 = truncate uniform int repeat = 0; // 0 = none, 1 = repeat, 2 = mirrored, 3 = truncate
@ -62,36 +69,42 @@ float dither(vec2 uv, float modified_uv, ivec2 image_size) {
void fragment() { void fragment() {
vec4 original_color = texture(TEXTURE, UV); vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV); vec4 selection_color = texture(selection, UV);
//vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE;
//vec2 uv = floor(UV * tex_size) / (tex_size - 1.0);
float modified_uv = modify_uv(UV); float modified_uv = modify_uv(UV);
if (repeat == 1) if (repeat == 1)
modified_uv = fract(modified_uv); modified_uv = fract(modified_uv);
else if (repeat == 2) else if (repeat == 2)
modified_uv = mirror_fract(modified_uv); modified_uv = mirror_fract(modified_uv);
int n_of_colors = textureSize(offset_texture, 0).x;
float colors_minus = float(n_of_colors - 1);
vec4 output; vec4 output;
for (int i = 1; i <= n_of_colors; i++) { if (use_dithering) {
float off = texture(offset_texture, vec2(float(i) / colors_minus)).r; int n_of_colors = textureSize(gradient_offset_texture, 0).x;
float off_prev = texture(offset_texture, vec2(float(i - 1) / colors_minus)).r; float colors_minus = float(n_of_colors - 1);
vec4 first = texture(gradient_texture, vec2(float((i - 1)) / colors_minus)); for (int i = 1; i <= n_of_colors; i++) {
vec4 second = texture(gradient_texture, vec2(float(i) / colors_minus)); float off = texture(gradient_offset_texture, vec2(float(i) / colors_minus)).r;
if (modified_uv < off_prev) { float off_prev = texture(gradient_offset_texture, vec2(float(i - 1) / colors_minus)).r;
if (i == 1) { vec4 first = texture(gradient_texture_no_interpolation, vec2(float((i - 1)) / colors_minus));
output = first; vec4 second = texture(gradient_texture_no_interpolation, vec2(float(i) / colors_minus));
if (modified_uv < off_prev) {
if (i == 1) {
output = first;
}
continue;
} }
continue; if (modified_uv > off) {
} if (i == n_of_colors) {
if (modified_uv > off) { output = second;
if (i == n_of_colors) { }
output = second; continue;
} }
continue; float uvt = (modified_uv - off_prev) / (off - off_prev);
float col_sample = dither(UV, uvt, textureSize(TEXTURE, 0));
output = mix(first, second, col_sample);
} }
float uvt = (modified_uv - off_prev) / (off - off_prev);
float col_sample = dither(UV, uvt, textureSize(TEXTURE, 0));
output = mix(first, second, col_sample);
} }
else
output = texture(gradient_texture, vec2(modified_uv));
if (repeat == 3) if (repeat == 3)
output.a = min(step(modified_uv, 1.0) * step(0.0, modified_uv), output.a); output.a = min(step(modified_uv, 1.0) * step(0.0, modified_uv), output.a);
output = mix(original_color, output, output.a); output = mix(original_color, output, output.a);

View file

@ -1,64 +0,0 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D selection : filter_nearest;
uniform sampler2D gradient_texture : filter_nearest;
uniform float position : hint_range(-0.5, 0.5) = 0.0;
uniform float size : hint_range(0.01, 2.0) = 1.0;
uniform float angle : hint_range(0.0, 360.0) = 0.0;
uniform vec2 center = vec2(0.5);
uniform vec2 radius = vec2(1.0);
uniform int shape = 0; // 0 = linear, 1 = radial
uniform int repeat = 0; // 0 = none, 1 = repeat, 2 = mirrored, 3 = truncate
float modify_uv(vec2 uv) {
float modified_uv;
if (shape == 0) { // Linear
vec2 uv_offsetted = uv - 0.5;
float angle_cos = cos(radians(angle));
float angle_sin = sin(radians(angle));
modified_uv = uv_offsetted.x * angle_cos - uv_offsetted.y * angle_sin;
modified_uv /= abs(angle_cos) + abs(angle_sin);
modified_uv /= size;
float pivot = position / size;
modified_uv -= pivot - 0.5;
}
else { // Radial
vec2 uv_offsetted = uv * 2.0 - 1.0;
uv_offsetted -= (center * 2.0) - vec2(1.0);
uv_offsetted /= radius;
modified_uv = length(uv_offsetted);
}
return modified_uv;
}
float mirror_fract(float uv) {
int sign_uv = (int(sign(uv)) - 1) / 2; // returns -1 for negative sign and 0 for positive
if (int((uv)) % 2 == sign_uv)
uv = fract(uv);
else
uv = fract(1.0 - uv);
return uv;
}
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE;
vec2 uv = floor(UV * tex_size) / (tex_size - 1.0);
float modified_uv = modify_uv(uv);
if (repeat == 1)
modified_uv = fract(modified_uv);
else if (repeat == 2)
modified_uv = mirror_fract(modified_uv);
vec4 output = texture(gradient_texture, vec2(modified_uv));
if (repeat == 3)
output.a = min(step(modified_uv, 1.0) * step(0.0, modified_uv), output.a);
output = mix(original_color, output, output.a);
COLOR = mix(original_color, output, selection_color.a);
}

View file

@ -3,10 +3,7 @@ extends ImageEffect
enum { LINEAR, RADIAL, LINEAR_DITHERING, RADIAL_DITHERING } enum { LINEAR, RADIAL, LINEAR_DITHERING, RADIAL_DITHERING }
enum Animate { POSITION, SIZE, ANGLE, CENTER_X, CENTER_Y, RADIUS_X, RADIUS_Y } enum Animate { POSITION, SIZE, ANGLE, CENTER_X, CENTER_Y, RADIUS_X, RADIUS_Y }
var shader_linear := preload("res://src/Shaders/Effects/Gradients/Linear.gdshader") var shader := preload("res://src/Shaders/Effects/Gradient.gdshader")
var shader_linear_dither := preload("res://src/Shaders/Effects/Gradients/LinearDithering.gdshader")
var shader := shader_linear
var selected_dither_matrix := ShaderLoader.dither_matrices[0] var selected_dither_matrix := ShaderLoader.dither_matrices[0]
@onready var options_cont: Container = $VBoxContainer/GradientOptions @onready var options_cont: Container = $VBoxContainer/GradientOptions
@ -51,11 +48,11 @@ func commit_action(cel: Image, project := Global.current_project) -> void:
var offsets := gradient.offsets var offsets := gradient.offsets
offsets.sort() offsets.sort()
var n_of_colors := offsets.size() var n_of_colors := offsets.size()
# Pass the gradient offsets as an array to the shader # Pass the gradient offsets as an array to the shader,
# ...but we can't provide arrays with variable sizes as uniforms, instead we construct # but we can't provide arrays with variable sizes as uniforms, instead we construct
# a nx1 grayscale texture with each offset stored in each pixel, and pass it to the shader # a Nx1 grayscale texture with each offset stored in each pixel, and pass it to the shader.
var offsets_image := Image.create(n_of_colors, 1, false, Image.FORMAT_L8) var offsets_image := Image.create(n_of_colors, 1, false, Image.FORMAT_L8)
# Construct an image that contains the selected colors of the gradient without interpolation # Construct an image that contains the selected colors of the gradient without interpolation.
var gradient_image := Image.create(n_of_colors, 1, false, Image.FORMAT_RGBA8) var gradient_image := Image.create(n_of_colors, 1, false, Image.FORMAT_RGBA8)
for i in n_of_colors: for i in n_of_colors:
var c := offsets[i] var c := offsets[i]
@ -64,12 +61,6 @@ func commit_action(cel: Image, project := Global.current_project) -> void:
if actual_index == -1: if actual_index == -1:
actual_index = i actual_index = i
gradient_image.set_pixel(i, 0, gradient.colors[actual_index]) gradient_image.set_pixel(i, 0, gradient.colors[actual_index])
var offsets_tex := ImageTexture.create_from_image(offsets_image)
var gradient_tex: Texture2D
if shader == shader_linear:
gradient_tex = gradient_edit.texture
else:
gradient_tex = ImageTexture.create_from_image(gradient_image)
var center := Vector2( var center := Vector2(
animate_panel.get_animated_value(commit_idx, Animate.CENTER_X), animate_panel.get_animated_value(commit_idx, Animate.CENTER_X),
animate_panel.get_animated_value(commit_idx, Animate.CENTER_Y) animate_panel.get_animated_value(commit_idx, Animate.CENTER_Y)
@ -79,8 +70,10 @@ func commit_action(cel: Image, project := Global.current_project) -> void:
animate_panel.get_animated_value(commit_idx, Animate.RADIUS_Y) animate_panel.get_animated_value(commit_idx, Animate.RADIUS_Y)
) )
var params := { var params := {
"gradient_texture": gradient_tex, "gradient_texture": gradient_edit.texture,
"offset_texture": offsets_tex, "gradient_texture_no_interpolation": ImageTexture.create_from_image(gradient_image),
"gradient_offset_texture": ImageTexture.create_from_image(offsets_image),
"use_dithering": dithering_option_button.selected > 0,
"selection": selection_tex, "selection": selection_tex,
"repeat": repeat_option_button.selected, "repeat": repeat_option_button.selected,
"position": (animate_panel.get_animated_value(commit_idx, Animate.POSITION) / 100.0) - 0.5, "position": (animate_panel.get_animated_value(commit_idx, Animate.POSITION) / 100.0) - 0.5,
@ -124,10 +117,7 @@ func _value_v2_changed(_value: Vector2) -> void:
func _on_DitheringOptionButton_item_selected(index: int) -> void: func _on_DitheringOptionButton_item_selected(index: int) -> void:
if index > 0: if index > 0:
shader = shader_linear_dither
selected_dither_matrix = ShaderLoader.dither_matrices[index - 1] selected_dither_matrix = ShaderLoader.dither_matrices[index - 1]
else:
shader = shader_linear
update_preview() update_preview()