diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.cpp b/src/renderer/wg_engine/tvgWgShaderSrc.cpp index d1fd4ba8..6485517a 100644 --- a/src/renderer/wg_engine/tvgWgShaderSrc.cpp +++ b/src/renderer/wg_engine/tvgWgShaderSrc.cpp @@ -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]) { diff --git a/src/renderer/wg_engine/tvgWgShaderTypes.cpp b/src/renderer/wg_engine/tvgWgShaderTypes.cpp index 253ea68a..0a14f782 100644 --- a/src/renderer/wg_engine/tvgWgShaderTypes.cpp +++ b/src/renderer/wg_engine/tvgWgShaderTypes.cpp @@ -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; diff --git a/src/renderer/wg_engine/tvgWgShaderTypes.h b/src/renderer/wg_engine/tvgWgShaderTypes.h index 681bec91..e44e5178 100644 --- a/src/renderer/wg_engine/tvgWgShaderTypes.h +++ b/src/renderer/wg_engine/tvgWgShaderTypes.h @@ -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);