Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add gradients to scene_rect #102

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions include/render/fx_renderer/shaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ struct quad_grad_shader {
GLint degree;
GLint grad_box;
GLint pos_attrib;
GLint linear;
GLint is_linear;
GLint origin;
GLint count;
GLint blend;
GLint should_blend;
};

bool link_quad_grad_program(struct quad_grad_shader *shader, int max_len);
Expand Down Expand Up @@ -93,10 +93,10 @@ struct quad_grad_round_shader {
GLint grad_size;
GLint degree;
GLint grad_box;
GLint linear;
GLint is_linear;
GLint origin;
GLint count;
GLint blend;
GLint should_blend;

GLint round_top_left;
GLint round_top_right;
Expand Down
25 changes: 5 additions & 20 deletions include/scenefx/render/pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "render/egl.h"
#include "scenefx/types/fx/clipped_region.h"
#include "scenefx/types/fx/corner_location.h"
#include "scenefx/types/fx/gradient.h"

struct fx_gles_render_pass {
struct wlr_render_pass base;
Expand Down Expand Up @@ -36,20 +37,6 @@ struct fx_gles_render_pass *fx_renderer_begin_buffer_pass(struct wlr_renderer *w
struct wlr_buffer *wlr_buffer, struct wlr_output *output,
const struct fx_buffer_pass_options *options);

struct fx_gradient {
float degree;
/* The full area the gradient fit too, for borders use the window size */
struct wlr_box range;
/* The center of the gradient, {0.5, 0.5} for normal*/
float origin[2];
/* 1 = Linear, 2 = Conic */
int linear;
/* Whether or not to blend the colors */
int blend;
int count;
float *colors;
};

struct fx_render_texture_options {
struct wlr_render_texture_options base;
const struct wlr_box *clip_box; // Used to clip csd. Ignored if NULL
Expand All @@ -64,8 +51,8 @@ struct fx_render_rect_options {
};

struct fx_render_rect_grad_options {
struct wlr_render_rect_options base;
struct fx_gradient gradient;
struct fx_render_rect_options rect_options;
struct gradient gradient;
};

struct fx_render_rounded_rect_options {
Expand All @@ -76,10 +63,8 @@ struct fx_render_rounded_rect_options {
};

struct fx_render_rounded_rect_grad_options {
struct wlr_render_rect_options base;
struct fx_gradient gradient;
int corner_radius;
enum corner_location corners;
struct fx_render_rounded_rect_options rounded_rect_options;
struct gradient gradient;
};

struct fx_render_box_shadow_options {
Expand Down
14 changes: 14 additions & 0 deletions include/scenefx/types/fx/gradient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef TYPES_FX_GRADIENT_H
#define TYPES_FX_GRADIENT_H

struct gradient {
float degree;
struct wlr_box range; // the full area the gradient fit to, for borders use the window size
float origin[2]; // center of the gradient, { 0.5, 0.5 } for normal
bool is_linear; // else is conic
float should_blend;
int count;
float *colors;
};

#endif // TYPES_FX_GRADIENT_H
18 changes: 17 additions & 1 deletion include/scenefx/types/wlr_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "scenefx/types/fx/blur_data.h"
#include "scenefx/types/fx/clipped_region.h"
#include "scenefx/types/fx/corner_location.h"
#include "scenefx/types/fx/gradient.h"

struct wlr_output;
struct wlr_output_layout;
Expand Down Expand Up @@ -91,6 +92,11 @@ enum wlr_scene_debug_damage_option {
WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT
};

enum wlr_scene_rect_fill_type {
SOLID_COLOR,
GRADIENT,
};

/** A sub-tree in the scene-graph. */
struct wlr_scene_tree {
struct wlr_scene_node node;
Expand Down Expand Up @@ -143,12 +149,17 @@ struct wlr_scene_surface {
struct wlr_scene_rect {
struct wlr_scene_node node;
int width, height;
float color[4];
int corner_radius;
enum corner_location corners;
bool backdrop_blur;
bool backdrop_blur_optimized;

union {
float color[4];
struct gradient gradient;
};
enum wlr_scene_rect_fill_type fill_type;

bool accepts_input;
struct clipped_region clipped_region;
};
Expand Down Expand Up @@ -441,6 +452,11 @@ void wlr_scene_rect_set_clipped_region(struct wlr_scene_rect *rect,
*/
void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]);

/**
* Change the gradient of an existing rectangle node.
*/
void wlr_scene_rect_set_gradient(struct wlr_scene_rect *rect, const struct gradient gradient);

/**
* Sets whether or not the buffer should render backdrop blur
*/
Expand Down
22 changes: 11 additions & 11 deletions render/fx_renderer/fx_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ void fx_render_pass_add_rect(struct fx_gles_render_pass *pass,

void fx_render_pass_add_rect_grad(struct fx_gles_render_pass *pass,
const struct fx_render_rect_grad_options *fx_options) {
const struct wlr_render_rect_options *options = &fx_options->base;
const struct wlr_render_rect_options *options = &fx_options->rect_options.base;

struct fx_renderer *renderer = pass->buffer->renderer;

Expand All @@ -429,8 +429,8 @@ void fx_render_pass_add_rect_grad(struct fx_gles_render_pass *pass,
glUniform1i(renderer->shaders.quad_grad.count, fx_options->gradient.count);
glUniform2f(renderer->shaders.quad_grad.size, fx_options->gradient.range.width, fx_options->gradient.range.height);
glUniform1f(renderer->shaders.quad_grad.degree, fx_options->gradient.degree);
glUniform1f(renderer->shaders.quad_grad.linear, fx_options->gradient.linear);
glUniform1f(renderer->shaders.quad_grad.blend, fx_options->gradient.blend);
glUniform1f(renderer->shaders.quad_grad.is_linear, fx_options->gradient.is_linear);
glUniform1f(renderer->shaders.quad_grad.should_blend, fx_options->gradient.should_blend);
glUniform2f(renderer->shaders.quad_grad.grad_box, fx_options->gradient.range.x, fx_options->gradient.range.y);
glUniform2f(renderer->shaders.quad_grad.origin, fx_options->gradient.origin[0], fx_options->gradient.origin[1]);

Expand Down Expand Up @@ -517,7 +517,7 @@ void fx_render_pass_add_rounded_rect(struct fx_gles_render_pass *pass,

void fx_render_pass_add_rounded_rect_grad(struct fx_gles_render_pass *pass,
const struct fx_render_rounded_rect_grad_options *fx_options) {
const struct wlr_render_rect_options *options = &fx_options->base;
const struct wlr_render_rect_options *options = &fx_options->rounded_rect_options.base;

struct fx_renderer *renderer = pass->buffer->renderer;

Expand All @@ -542,25 +542,25 @@ void fx_render_pass_add_rounded_rect_grad(struct fx_gles_render_pass *pass,

glUniform2f(shader.size, box.width, box.height);
glUniform2f(shader.position, box.x, box.y);
glUniform1f(shader.radius, fx_options->corner_radius);
glUniform1f(shader.radius, fx_options->rounded_rect_options.corner_radius);

glUniform4fv(shader.colors, fx_options->gradient.count, (GLfloat*)fx_options->gradient.colors);
glUniform1i(shader.count, fx_options->gradient.count);
glUniform2f(shader.grad_size, fx_options->gradient.range.width, fx_options->gradient.range.height);
glUniform1f(shader.degree, fx_options->gradient.degree);
glUniform1f(shader.linear, fx_options->gradient.linear);
glUniform1f(shader.blend, fx_options->gradient.blend);
glUniform1f(shader.is_linear, fx_options->gradient.is_linear);
glUniform1f(shader.should_blend, fx_options->gradient.should_blend);
glUniform2f(shader.grad_box, fx_options->gradient.range.x, fx_options->gradient.range.y);
glUniform2f(shader.origin, fx_options->gradient.origin[0], fx_options->gradient.origin[1]);

glUniform1f(shader.round_top_left,
(CORNER_LOCATION_TOP_LEFT & fx_options->corners) == CORNER_LOCATION_TOP_LEFT);
(CORNER_LOCATION_TOP_LEFT & fx_options->rounded_rect_options.corners) == CORNER_LOCATION_TOP_LEFT);
glUniform1f(shader.round_top_right,
(CORNER_LOCATION_TOP_RIGHT & fx_options->corners) == CORNER_LOCATION_TOP_RIGHT);
(CORNER_LOCATION_TOP_RIGHT & fx_options->rounded_rect_options.corners) == CORNER_LOCATION_TOP_RIGHT);
glUniform1f(shader.round_bottom_left,
(CORNER_LOCATION_BOTTOM_LEFT & fx_options->corners) == CORNER_LOCATION_BOTTOM_LEFT);
(CORNER_LOCATION_BOTTOM_LEFT & fx_options->rounded_rect_options.corners) == CORNER_LOCATION_BOTTOM_LEFT);
glUniform1f(shader.round_bottom_right,
(CORNER_LOCATION_BOTTOM_RIGHT & fx_options->corners) == CORNER_LOCATION_BOTTOM_RIGHT);
(CORNER_LOCATION_BOTTOM_RIGHT & fx_options->rounded_rect_options.corners) == CORNER_LOCATION_BOTTOM_RIGHT);

render(&box, options->clip, shader.pos_attrib);

Expand Down
19 changes: 10 additions & 9 deletions render/fx_renderer/gles2/shaders/gradient.frag
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
vec4 gradient(vec4 colors[LEN], int count, vec2 size, vec2 grad_box, vec2 origin, float degree, bool linear, bool blend) {
vec4 gradient(vec4 colors[LEN], int count, vec2 size, vec2 grad_box,
vec2 origin, float degree, bool is_linear, bool should_blend) {
float step;

vec2 normal = (gl_FragCoord.xy - grad_box)/size;
vec2 uv = normal - origin;

float rad = radians(degree);

if (linear) {
if (is_linear) {
uv *= vec2(1.0)/vec2(abs(cos(rad)) + abs(sin(rad)));

vec2 rotated = vec2(uv.x * cos(rad) - uv.y * sin(rad) + origin.x,
Expand All @@ -18,20 +19,20 @@ vec4 gradient(vec4 colors[LEN], int count, vec2 size, vec2 grad_box, vec2 origin
uv = vec2(uv.x * cos(rad) - uv.y * sin(rad),
uv.x * sin(rad) + uv.y * cos(rad));

uv = vec2(-atan(uv.y, uv.x)/3.14159265 * 0.5 + 0.5, 0.0);
uv = vec2(-atan(uv.y, uv.x) / 3.14159265 * 0.5 + 0.5, 0.0);
step = uv.x;
}

if (!blend) {
float smooth = 1.0/float(count);
int ind = int(step/smooth);
if (!should_blend) {
float smooth = 1.0 / float(count);
int ind = int(step / smooth);

return colors[ind];
}

float smooth = 1.0/float(count - 1);
int ind = int(step/smooth);
float at = float(ind)*smooth;
float smooth = 1.0 / float(count - 1);
int ind = int(step / smooth);
float at = float(ind) * smooth;

vec4 color = colors[ind];
if(ind > 0) color = mix(colors[ind - 1], color, smoothstep(at - smooth, at, step));
Expand Down
10 changes: 6 additions & 4 deletions render/fx_renderer/gles2/shaders/quad_grad.frag
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ uniform vec2 size;
uniform float degree;
uniform vec2 grad_box;
uniform vec2 origin;
uniform bool linear;
uniform bool blend;
uniform bool is_linear;
uniform bool should_blend;
uniform int count;

vec4 gradient(vec4 colors[LEN], int count, vec2 size, vec2 grad_box, vec2 origin, float degree, bool linear, bool blend);
vec4 gradient(vec4 colors[LEN], int count, vec2 size, vec2 grad_box,
vec2 origin, float degree, bool is_linear, bool should_blend);

void main(){
gl_FragColor = gradient(colors, count, size, grad_box, origin, degree, linear, blend);
gl_FragColor = gradient(colors, count, size, grad_box,
origin, degree, is_linear, should_blend);
}
14 changes: 9 additions & 5 deletions render/fx_renderer/gles2/shaders/quad_grad_round.frag
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ uniform vec2 grad_size;
uniform float degree;
uniform vec2 grad_box;
uniform vec2 origin;
uniform bool linear;
uniform bool blend;
uniform bool is_linear;
uniform bool should_blend;
uniform int count;

uniform bool round_top_left;
uniform bool round_top_right;
uniform bool round_bottom_left;
uniform bool round_bottom_right;

vec4 gradient(vec4 colors[LEN], int count, vec2 size, vec2 grad_box, vec2 origin, float degree, bool linear, bool blend);
vec4 gradient(vec4 colors[LEN], int count, vec2 size, vec2 grad_box,
vec2 origin, float degree, bool is_linear, bool should_blend);

float corner_alpha(vec2 size, vec2 position, float round_tl, float round_tr, float round_bl, float round_br);

// TODO:
void main() {
float quad_corner_alpha = corner_alpha(
size,
Expand All @@ -36,5 +36,9 @@ void main() {
);
float rect_alpha = v_color.a * quad_corner_alpha;

gl_FragColor = mix(vec4(0), gradient(colors, count, size, grad_box, origin, degree, linear, blend), rect_alpha);
gl_FragColor = mix(
vec4(0.0),
gradient(colors, count, size, grad_box, origin, degree, is_linear, should_blend),
rect_alpha
);
}
8 changes: 4 additions & 4 deletions render/fx_renderer/shaders.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ bool link_quad_grad_program(struct quad_grad_shader *shader, int max_len) {
shader->colors = glGetUniformLocation(prog, "colors");
shader->degree = glGetUniformLocation(prog, "degree");
shader->grad_box = glGetUniformLocation(prog, "grad_box");
shader->linear = glGetUniformLocation(prog, "linear");
shader->is_linear = glGetUniformLocation(prog, "is_linear");
shader->origin = glGetUniformLocation(prog, "origin");
shader->count = glGetUniformLocation(prog, "count");
shader->blend = glGetUniformLocation(prog, "blend");
shader->should_blend = glGetUniformLocation(prog, "should_blend");

shader->max_len = max_len;

Expand Down Expand Up @@ -210,10 +210,10 @@ bool link_quad_grad_round_program(struct quad_grad_round_shader *shader, int max
shader->colors = glGetUniformLocation(prog, "colors");
shader->degree = glGetUniformLocation(prog, "degree");
shader->grad_box = glGetUniformLocation(prog, "grad_box");
shader->linear = glGetUniformLocation(prog, "linear");
shader->is_linear = glGetUniformLocation(prog, "is_linear");
shader->origin = glGetUniformLocation(prog, "origin");
shader->count = glGetUniformLocation(prog, "count");
shader->blend = glGetUniformLocation(prog, "blend");
shader->should_blend = glGetUniformLocation(prog, "should_blend");

shader->round_top_left = glGetUniformLocation(prog, "round_top_left");
shader->round_top_right = glGetUniformLocation(prog, "round_top_right");
Expand Down
33 changes: 22 additions & 11 deletions tinywl/tinywl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1142,26 +1142,37 @@ int main(int argc, char *argv[]) {

/* Create all of the basic scene layers */
server.layers.bottom_layer = wlr_scene_tree_create(&server.scene->tree);

/* Add a bottom rect to demonstrate optimized blur */
float bottom_rect_color[4] = { 1, 1, 1, 1 };
wlr_scene_rect_create(server.layers.bottom_layer, 200, 200, bottom_rect_color);
struct wlr_scene_rect *bottom_rect = wlr_scene_rect_create(server.layers.bottom_layer,
200, 200, bottom_rect_color);
wlr_scene_rect_set_gradient(
bottom_rect,
(struct gradient) {
.degree = 0.0,
.range = (struct wlr_box) {
.x = 0,
.y = 0,
.width = 200,
.height = 200,
},
.origin = { 0.5, 0.5 },
.is_linear = true,
.should_blend = true,
.count = 1,
.colors = bottom_rect_color,
}
);

/* Set the size later */
server.layers.blur_layer = wlr_scene_optimized_blur_create(&server.scene->tree, 0, 0);
server.layers.toplevel_layer = wlr_scene_tree_create(&server.scene->tree);

/* Add a top rect that won't get blurred by optimized */
float top_rect_color[4] = { 1, 0, 0, 1 };
struct wlr_scene_rect *rect = wlr_scene_rect_create(server.layers.toplevel_layer,
200, 200, top_rect_color);
wlr_scene_rect_set_clipped_region(rect, (struct clipped_region) {
.corner_radius = 12,
.corners = CORNER_LOCATION_TOP,
.area = {
.x = 50,
.y = 50,
.width = 100,
.height = 100,
},
});
wlr_scene_node_set_position(&rect->node, 200, 200);

// blur
Expand Down
Loading