forked from AuroraMiddleware/gtk
gl renderer: Add radial gradient shader
This commit is contained in:
parent
2c5a4a799a
commit
b8e4240751
@ -1192,6 +1192,32 @@ render_linear_gradient_node (GskGLRenderer *self,
|
||||
load_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
}
|
||||
|
||||
static inline void
|
||||
render_radial_gradient_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const int n_color_stops = MIN (8, gsk_radial_gradient_node_get_n_color_stops (node));
|
||||
const GskColorStop *stops = gsk_radial_gradient_node_peek_color_stops (node, NULL);
|
||||
const graphene_point_t *center = gsk_radial_gradient_node_peek_center (node);
|
||||
const float start = gsk_radial_gradient_node_get_start (node);
|
||||
const float end = gsk_radial_gradient_node_get_end (node);
|
||||
const float hradius = gsk_radial_gradient_node_get_hradius (node);
|
||||
const float vradius = gsk_radial_gradient_node_get_vradius (node);
|
||||
|
||||
ops_set_program (builder, &self->programs->radial_gradient_program);
|
||||
ops_set_radial_gradient (builder,
|
||||
n_color_stops,
|
||||
stops,
|
||||
builder->dx + center->x,
|
||||
builder->dy + center->y,
|
||||
start, end,
|
||||
hradius * scale, vradius * scale);
|
||||
|
||||
load_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
|
||||
const graphene_rect_t *rect)
|
||||
@ -2761,6 +2787,25 @@ apply_linear_gradient_op (const Program *program,
|
||||
glUniform2f (program->linear_gradient.end_point_location, op->end_point[0], op->end_point[1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_radial_gradient_op (const Program *program,
|
||||
const OpRadialGradient *op)
|
||||
{
|
||||
OP_PRINT (" -> Radial gradient");
|
||||
if (op->n_color_stops.send)
|
||||
glUniform1i (program->radial_gradient.num_color_stops_location, op->n_color_stops.value);
|
||||
|
||||
if (op->color_stops.send)
|
||||
glUniform1fv (program->radial_gradient.color_stops_location,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform1f (program->radial_gradient.start_location, op->start);
|
||||
glUniform1f (program->radial_gradient.end_location, op->end);
|
||||
glUniform2f (program->radial_gradient.radius_location, op->radius[0], op->radius[1]);
|
||||
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_border_op (const Program *program,
|
||||
const OpBorder *op)
|
||||
@ -2903,6 +2948,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
{ "/org/gtk/libgsk/glsl/cross_fade.glsl", "cross fade" },
|
||||
{ "/org/gtk/libgsk/glsl/inset_shadow.glsl", "inset shadow" },
|
||||
{ "/org/gtk/libgsk/glsl/linear_gradient.glsl", "linear gradient" },
|
||||
{ "/org/gtk/libgsk/glsl/radial_gradient.glsl", "radial gradient" },
|
||||
{ "/org/gtk/libgsk/glsl/outset_shadow.glsl", "outset shadow" },
|
||||
{ "/org/gtk/libgsk/glsl/repeat.glsl", "repeat" },
|
||||
{ "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl", "unblurred_outset shadow" },
|
||||
@ -2984,6 +3030,14 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, start_point);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, end_point);
|
||||
|
||||
/* radial gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, center);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, start);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
|
||||
|
||||
/* blur */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_size);
|
||||
@ -3332,6 +3386,10 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
render_linear_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
render_radial_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
render_clip_node (self, node, builder);
|
||||
break;
|
||||
@ -3388,7 +3446,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
default:
|
||||
@ -3684,6 +3741,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self)
|
||||
apply_linear_gradient_op (program, ptr);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_RADIAL_GRADIENT:
|
||||
apply_radial_gradient_op (program, ptr);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_BLUR:
|
||||
apply_blur_op (program, ptr);
|
||||
break;
|
||||
|
@ -960,3 +960,32 @@ ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
op->end_point[0] = end_x;
|
||||
op->end_point[1] = end_y;
|
||||
}
|
||||
|
||||
void
|
||||
ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
float end,
|
||||
float hradius,
|
||||
float vradius)
|
||||
{
|
||||
const guint real_n_color_stops = MIN (MAX_GRADIENT_STOPS, n_color_stops);
|
||||
OpRadialGradient *op;
|
||||
|
||||
/* TODO: State tracking? */
|
||||
|
||||
op = ops_begin (self, OP_CHANGE_RADIAL_GRADIENT);
|
||||
op->n_color_stops.value = real_n_color_stops;
|
||||
op->n_color_stops.send = true;
|
||||
op->color_stops.value = color_stops;
|
||||
op->color_stops.send = true;
|
||||
op->center[0] = center_x;
|
||||
op->center[1] = center_y;
|
||||
op->radius[0] = hradius;
|
||||
op->radius[1] = vradius;
|
||||
op->start = start;
|
||||
op->end = end;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "opbuffer.h"
|
||||
|
||||
#define GL_N_VERTICES 6
|
||||
#define GL_N_PROGRAMS 13
|
||||
#define GL_N_PROGRAMS 14
|
||||
#define MAX_GRADIENT_STOPS 8
|
||||
|
||||
typedef struct
|
||||
@ -62,6 +62,14 @@ struct _Program
|
||||
int start_point_location;
|
||||
int end_point_location;
|
||||
} linear_gradient;
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int center_location;
|
||||
int start_location;
|
||||
int end_location;
|
||||
int radius_location;
|
||||
} radial_gradient;
|
||||
struct {
|
||||
int blur_radius_location;
|
||||
int blur_size_location;
|
||||
@ -143,6 +151,14 @@ typedef struct
|
||||
float start_point[2];
|
||||
float end_point[2];
|
||||
} linear_gradient;
|
||||
struct {
|
||||
int n_color_stops;
|
||||
GskColorStop color_stops[MAX_GRADIENT_STOPS];
|
||||
float center[2];
|
||||
float start;
|
||||
float end;
|
||||
float radius[2]; /* h/v */
|
||||
} radial_gradient;
|
||||
};
|
||||
} ProgramState;
|
||||
|
||||
@ -161,6 +177,7 @@ typedef struct {
|
||||
Program cross_fade_program;
|
||||
Program inset_shadow_program;
|
||||
Program linear_gradient_program;
|
||||
Program radial_gradient_program;
|
||||
Program outset_shadow_program;
|
||||
Program repeat_program;
|
||||
Program unblurred_outset_shadow_program;
|
||||
@ -278,6 +295,15 @@ void ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
float start_y,
|
||||
float end_x,
|
||||
float end_y);
|
||||
void ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
float end,
|
||||
float hradius,
|
||||
float vradius);
|
||||
|
||||
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES]);
|
||||
|
@ -15,6 +15,7 @@ static guint op_sizes[OP_LAST] = {
|
||||
sizeof (OpTexture),
|
||||
sizeof (OpRepeat),
|
||||
sizeof (OpLinearGradient),
|
||||
sizeof (OpRadialGradient),
|
||||
sizeof (OpColorMatrix),
|
||||
sizeof (OpBlur),
|
||||
sizeof (OpShadow),
|
||||
|
@ -23,21 +23,22 @@ typedef enum
|
||||
OP_CHANGE_SOURCE_TEXTURE = 9,
|
||||
OP_CHANGE_REPEAT = 10,
|
||||
OP_CHANGE_LINEAR_GRADIENT = 11,
|
||||
OP_CHANGE_COLOR_MATRIX = 12,
|
||||
OP_CHANGE_BLUR = 13,
|
||||
OP_CHANGE_INSET_SHADOW = 14,
|
||||
OP_CHANGE_OUTSET_SHADOW = 15,
|
||||
OP_CHANGE_BORDER = 16,
|
||||
OP_CHANGE_BORDER_COLOR = 17,
|
||||
OP_CHANGE_BORDER_WIDTH = 18,
|
||||
OP_CHANGE_CROSS_FADE = 19,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
|
||||
OP_CLEAR = 21,
|
||||
OP_DRAW = 22,
|
||||
OP_DUMP_FRAMEBUFFER = 23,
|
||||
OP_PUSH_DEBUG_GROUP = 24,
|
||||
OP_POP_DEBUG_GROUP = 25,
|
||||
OP_CHANGE_BLEND = 26,
|
||||
OP_CHANGE_RADIAL_GRADIENT = 12,
|
||||
OP_CHANGE_COLOR_MATRIX = 13,
|
||||
OP_CHANGE_BLUR = 14,
|
||||
OP_CHANGE_INSET_SHADOW = 15,
|
||||
OP_CHANGE_OUTSET_SHADOW = 16,
|
||||
OP_CHANGE_BORDER = 17,
|
||||
OP_CHANGE_BORDER_COLOR = 18,
|
||||
OP_CHANGE_BORDER_WIDTH = 19,
|
||||
OP_CHANGE_CROSS_FADE = 20,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 21,
|
||||
OP_CLEAR = 22,
|
||||
OP_DRAW = 23,
|
||||
OP_DUMP_FRAMEBUFFER = 24,
|
||||
OP_PUSH_DEBUG_GROUP = 25,
|
||||
OP_POP_DEBUG_GROUP = 26,
|
||||
OP_CHANGE_BLEND = 27,
|
||||
OP_LAST
|
||||
} OpKind;
|
||||
|
||||
@ -137,6 +138,16 @@ typedef struct
|
||||
float end_point[2];
|
||||
} OpLinearGradient;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ColorStopUniformValue color_stops;
|
||||
IntUniformValue n_color_stops;
|
||||
float start;
|
||||
float end;
|
||||
float radius[2];
|
||||
float center[2];
|
||||
} OpRadialGradient;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const graphene_matrix_t *matrix;
|
||||
|
@ -394,8 +394,6 @@ struct _GskRadialGradientNode
|
||||
|
||||
graphene_point_t center;
|
||||
|
||||
gboolean circle;
|
||||
|
||||
float hradius;
|
||||
float vradius;
|
||||
float start;
|
||||
|
@ -7,6 +7,7 @@ gsk_private_gl_shaders = [
|
||||
'resources/glsl/coloring.glsl',
|
||||
'resources/glsl/color.glsl',
|
||||
'resources/glsl/linear_gradient.glsl',
|
||||
'resources/glsl/radial_gradient.glsl',
|
||||
'resources/glsl/color_matrix.glsl',
|
||||
'resources/glsl/blur.glsl',
|
||||
'resources/glsl/inset_shadow.glsl',
|
||||
|
89
gsk/resources/glsl/radial_gradient.glsl
Normal file
89
gsk/resources/glsl/radial_gradient.glsl
Normal file
@ -0,0 +1,89 @@
|
||||
// VERTEX_SHADER
|
||||
uniform float u_start;
|
||||
uniform float u_end;
|
||||
uniform float u_color_stops[8 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec2 u_radius;
|
||||
uniform vec2 u_center;
|
||||
|
||||
_OUT_ vec2 center;
|
||||
_OUT_ vec4 color_stops[8];
|
||||
_OUT_ float color_offsets[8];
|
||||
_OUT_ float start;
|
||||
_OUT_ float end;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
center = (u_modelview * vec4(u_center, 0, 1)).xy;
|
||||
start = u_start;
|
||||
end = u_end;
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i].r = u_color_stops[(i * 5) + 1];
|
||||
color_stops[i].g = u_color_stops[(i * 5) + 2];
|
||||
color_stops[i].b = u_color_stops[(i * 5) + 3];
|
||||
color_stops[i].a = u_color_stops[(i * 5) + 4];
|
||||
}
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
#ifdef GSK_LEGACY
|
||||
uniform int u_num_color_stops;
|
||||
#else
|
||||
uniform highp int u_num_color_stops;
|
||||
#endif
|
||||
|
||||
uniform vec2 u_radius;
|
||||
uniform float u_end;
|
||||
|
||||
_IN_ vec2 center;
|
||||
_IN_ vec4 color_stops[8];
|
||||
_IN_ float color_offsets[8];
|
||||
_IN_ float start;
|
||||
_IN_ float end;
|
||||
|
||||
// The offsets in the color stops are relative to the
|
||||
// start and end values of the gradient.
|
||||
float abs_offset(float offset) {
|
||||
return start + ((end - start) * offset);
|
||||
}
|
||||
|
||||
vec4 premultiply(vec4 c) {
|
||||
vec4 k = vec4(c.rgb * c.a, c.a);
|
||||
return k;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 pixel = get_frag_coord();
|
||||
vec2 rel = (center - pixel) / (u_radius);
|
||||
float d = sqrt(dot(rel, rel));
|
||||
|
||||
if (d < abs_offset (color_offsets[0])) {
|
||||
setOutputColor(premultiply(color_stops[0]) * u_alpha);
|
||||
return;
|
||||
}
|
||||
|
||||
if (d > end) {
|
||||
setOutputColor(premultiply(color_stops[u_num_color_stops - 1]) * u_alpha);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 color = vec4(0, 0, 0, 0);
|
||||
for (int i = 1; i < u_num_color_stops; i++) {
|
||||
float last_offset = abs_offset(color_offsets[i - 1]);
|
||||
float this_offset = abs_offset(color_offsets[i]);
|
||||
|
||||
// We have color_stops[i - 1] at last_offset and color_stops[i] at this_offset.
|
||||
// We now need to map `d` between those two offsets and simply mix linearly between them
|
||||
if (d >= last_offset && d <= this_offset) {
|
||||
float f = (d - last_offset) / (this_offset - last_offset);
|
||||
|
||||
color = mix(color_stops[i - 1], color_stops[i], f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setOutputColor(premultiply(color) * u_alpha);
|
||||
}
|
Loading…
Reference in New Issue
Block a user