wg_engine: fill spread

[issues 1479: LinearGradient, RadialGradient](#1479)

Introduced fill spreads: Pad, Reflect, Repeat

Pad:

Reflect:

Repeat:
This commit is contained in:
Sergii Liebodkin 2024-03-06 20:07:20 +02:00 committed by Hermet Park
parent 44da074d58
commit 4b2f5ca510
3 changed files with 56 additions and 22 deletions

View file

@ -126,7 +126,10 @@ struct BlendSettigs {
// LinearGradient
const MAX_LINEAR_GRADIENT_STOPS = 4;
struct LinearGradient {
nStops : vec4f,
nStops : u32,
spread : u32,
dummy0 : u32,
dummy1 : u32,
gradStartPos : vec2f,
gradEndPos : vec2f,
stopPoints : vec4f,
@ -166,10 +169,18 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let ba: vec2f = ed - st;
// get interpolation factor
let t: f32 = clamp(dot(pos - st, ba) / dot(ba, ba), 0.0, 1.0);
var t: f32 = abs(dot(pos - st, ba) / dot(ba, ba));
// fill spread
switch uLinearGradient.spread {
/* Pad */ case 0u: { t = clamp(t, 0.0, 1.0); }
/* Reflect */ case 1u: { t = select(1.0 - fract(t), fract(t), u32(t) % 2 == 0); }
/* Repeat */ case 2u: { t = fract(t); }
default: { t = t; }
}
// get stops count
let last: i32 = i32(uLinearGradient.nStops[0]) - 1;
let last: i32 = i32(uLinearGradient.nStops) - 1;
// closer than first stop
if (t <= uLinearGradient.stopPoints[0]) {
@ -216,7 +227,10 @@ struct BlendSettigs {
// RadialGradient
const MAX_RADIAL_GRADIENT_STOPS = 4;
struct RadialGradient {
nStops : vec4f,
nStops : u32,
spread : u32,
dummy0 : u32,
dummy1 : u32,
centerPos : vec2f,
radius : vec2f,
stopPoints : vec4f,
@ -250,10 +264,18 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
var color = vec4(1.0);
// get interpolation factor
let t: f32 = clamp(distance(uRadialGradient.centerPos, in.vScreenCoord) / uRadialGradient.radius.x, 0.0, 1.0);
var t: f32 = distance(uRadialGradient.centerPos, in.vScreenCoord) / uRadialGradient.radius.x;
// fill spread
switch uRadialGradient.spread {
/* Pad */ case 0u: { t = clamp(t, 0.0, 1.0); }
/* Reflect */ case 1u: { t = select(1.0 - fract(t), fract(t), u32(t) % 2 == 0); }
/* Repeat */ case 2u: { t = fract(t); }
default: { t = t; }
}
// get stops count
let last: i32 = i32(uRadialGradient.nStops[0]) - 1;
let last: i32 = i32(uRadialGradient.nStops) - 1;
// closer than first stop
if (t <= uRadialGradient.stopPoints[0]) {

View file

@ -127,8 +127,8 @@ void WgShaderTypeLinearGradient::update(const LinearGradient* linearGradient)
const Fill::ColorStop* stops = nullptr;
auto stopCnt = linearGradient->colorStops(&stops);
nStops[0] = stopCnt;
nStops[1] = 0.5f;
nStops = stopCnt;
spread = uint32_t(linearGradient->spread());
for (uint32_t i = 0; i < stopCnt; ++i) {
stopPoints[i] = stops[i].offset;
@ -153,8 +153,8 @@ void WgShaderTypeRadialGradient::update(const RadialGradient* radialGradient)
const Fill::ColorStop* stops = nullptr;
auto stopCnt = radialGradient->colorStops(&stops);
nStops[0] = stopCnt;
nStops[1] = 0.5f;
nStops = stopCnt;
spread = uint32_t(radialGradient->spread());
for (uint32_t i = 0; i < stopCnt; ++i) {
stopPoints[i] = stops[i].offset;

View file

@ -73,7 +73,10 @@ struct WgShaderTypeSolidColor
// const MAX_LINEAR_GRADIENT_STOPS = 4;
// struct LinearGradient {
// nStops : vec4f,
// nStops : u32,
// spread : u32,
// dummy0 : u32,
// dummy1 : u32,
// gradStartPos : vec2f,
// gradEndPos : vec2f,
// stopPoints : vec4f,
@ -82,11 +85,14 @@ struct WgShaderTypeSolidColor
#define MAX_LINEAR_GRADIENT_STOPS 4
struct WgShaderTypeLinearGradient
{
alignas(16) float nStops[4]{};
alignas(16) float startPos[2]{};
alignas(8) float endPos[2]{};
alignas(8) float stopPoints[MAX_LINEAR_GRADIENT_STOPS]{};
alignas(16) float stopColors[4 * MAX_LINEAR_GRADIENT_STOPS]{};
uint32_t nStops{};
uint32_t spread{};
uint32_t dummy0{}; // allign with WGSL struct
uint32_t dummy1{}; // allign with WGSL struct
float startPos[2]{};
float endPos[2]{};
float stopPoints[MAX_LINEAR_GRADIENT_STOPS]{};
float stopColors[4 * MAX_LINEAR_GRADIENT_STOPS]{};
WgShaderTypeLinearGradient(const LinearGradient* linearGradient);
void update(const LinearGradient* linearGradient);
@ -94,7 +100,10 @@ struct WgShaderTypeLinearGradient
// const MAX_RADIAL_GRADIENT_STOPS = 4;
// struct RadialGradient {
// nStops : vec4f,
// nStops : u32,
// spread : u32,
// dummy0 : u32,
// dummy1 : u32,
// centerPos : vec2f,
// radius : vec2f,
// stopPoints : vec4f,
@ -103,11 +112,14 @@ struct WgShaderTypeLinearGradient
#define MAX_RADIAL_GRADIENT_STOPS 4
struct WgShaderTypeRadialGradient
{
alignas(16) float nStops[4]{};
alignas(16) float centerPos[2]{};
alignas(8) float radius[2]{};
alignas(8) float stopPoints[MAX_RADIAL_GRADIENT_STOPS]{};
alignas(16) float stopColors[4 * MAX_RADIAL_GRADIENT_STOPS]{};
uint32_t nStops{};
uint32_t spread{};
uint32_t dummy0{}; // allign with WGSL struct
uint32_t dummy1{}; // allign with WGSL struct
float centerPos[2]{};
float radius[2]{};
float stopPoints[MAX_RADIAL_GRADIENT_STOPS]{};
float stopColors[4 * MAX_RADIAL_GRADIENT_STOPS]{};
WgShaderTypeRadialGradient(const RadialGradient* radialGradient);
void update(const RadialGradient* radialGradient);