From 627f358f4937e6eb354e45a281764eaf955f7650 Mon Sep 17 00:00:00 2001 From: Sergii Liebodkin Date: Wed, 6 Nov 2024 22:09:54 +0000 Subject: [PATCH] wg_engine: support gradient focal point Implemented gradien focal points Issue https://github.com/thorvg/thorvg/issues/2728 Issue https://github.com/thorvg/thorvg/issues/2936 --- src/renderer/wg_engine/tvgWgShaderSrc.cpp | 38 +++++++++++++++------ src/renderer/wg_engine/tvgWgShaderTypes.cpp | 2 +- src/renderer/wg_engine/tvgWgShaderTypes.h | 2 +- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.cpp b/src/renderer/wg_engine/tvgWgShaderSrc.cpp index 89ef5f0b..282f5348 100755 --- a/src/renderer/wg_engine/tvgWgShaderSrc.cpp +++ b/src/renderer/wg_engine/tvgWgShaderSrc.cpp @@ -111,6 +111,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { const char* cShaderSrc_Linear = R"( struct VertexInput { @location(0) position: vec2f }; struct VertexOutput { @builtin(position) position : vec4f, @location(0) vGradCoord : vec4f }; +struct GradSettings { settings: vec4f, focal: vec4f }; // uniforms @group(0) @binding(0) var uViewMat : mat4x4f; @@ -118,7 +119,7 @@ struct VertexOutput { @builtin(position) position : vec4f, @location(0) vGradCoo @group(1) @binding(1) var uBlendSettings : vec4f; @group(2) @binding(0) var uSamplerGrad : sampler; @group(2) @binding(1) var uTextureGrad : texture_2d; -@group(2) @binding(2) var uSettingGrad : vec4f; +@group(2) @binding(2) var uSettingGrad : GradSettings; @group(2) @binding(3) var uTransformGrad : mat4x4f; @vertex @@ -132,8 +133,8 @@ fn vs_main(in: VertexInput) -> VertexOutput { @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let pos = in.vGradCoord.xy; - let st = uSettingGrad.xy; - let ed = uSettingGrad.zw; + let st = uSettingGrad.settings.xy; + let ed = uSettingGrad.settings.zw; let ba = ed - st; let t = dot(pos - st, ba) / dot(ba, ba); let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5)); @@ -149,13 +150,14 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { const char* cShaderSrc_Radial = R"( struct VertexInput { @location(0) position: vec2f }; struct VertexOutput { @builtin(position) position : vec4f, @location(0) vGradCoord : vec4f }; +struct GradSettings { settings: vec4f, focal: vec4f }; @group(0) @binding(0) var uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @group(1) @binding(1) var uBlendSettings : vec4f; @group(2) @binding(0) var uSamplerGrad : sampler; @group(2) @binding(1) var uTextureGrad : texture_2d; -@group(2) @binding(2) var uSettingGrad : vec4f; +@group(2) @binding(2) var uSettingGrad : GradSettings; @group(2) @binding(3) var uTransformGrad : mat4x4f; @vertex @@ -168,8 +170,16 @@ fn vs_main(in: VertexInput) -> VertexOutput { @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - let t: f32 = distance(uSettingGrad.zw, in.vGradCoord.xy) / uSettingGrad.r; - let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5)); + // orignal data + let d0 = in.vGradCoord.xy - uSettingGrad.settings.xy; + let d1 = uSettingGrad.settings.xy - uSettingGrad.focal.xy; + let r0 = uSettingGrad.settings.z; + let rd = uSettingGrad.focal.z - uSettingGrad.settings.z; + let a = 1.0*dot(d1, d1) - 1.0*rd*rd; + let b = 2.0*dot(d0, d1) - 2.0*r0*rd; + let c = 1.0*dot(d0, d0) - 1.0*r0*r0; + let t = (-b + sqrt(b*b - 4*a*c))/(2*a); + let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(1.0 - t, 0.5)); let So = uBlendSettings.a; return vec4f(Sc.rgb * Sc.a * So, Sc.a * So); } @@ -286,6 +296,7 @@ fn postProcess(d: FragData, R: vec4f) -> vec4f { return R; }; const char* cShaderSrc_Linear_Blend = R"( struct VertexInput { @location(0) position: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) vGradCoord : vec4f, @location(1) vScrCoord: vec2f }; +struct GradSettings { settings: vec4f, focal: vec4f }; @group(0) @binding(0) var uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @@ -335,13 +346,14 @@ fn postProcess(d: FragData, R: vec4f) -> vec4f { return R; }; const char* cShaderSrc_Radial_Blend = R"( struct VertexInput { @location(0) position: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) vGradCoord : vec4f, @location(1) vScrCoord: vec2f }; +struct GradSettings { settings: vec4f, focal: vec4f }; @group(0) @binding(0) var uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @group(1) @binding(1) var uBlendSettings : vec4f; @group(2) @binding(0) var uSamplerGrad : sampler; @group(2) @binding(1) var uTextureGrad : texture_2d; -@group(2) @binding(2) var uSettingGrad : vec4f; +@group(2) @binding(2) var uSettingGrad : GradSettings; @group(2) @binding(3) var uTransformGrad : mat4x4f; @group(3) @binding(0) var uSamplerDst : sampler; @group(3) @binding(1) var uTextureDst : texture_2d; @@ -358,9 +370,15 @@ fn vs_main(in: VertexInput) -> VertexOutput { struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 }; fn getFragData(in: VertexOutput) -> FragData { - // get source data - let t: f32 = distance(uSettingGrad.zw, in.vGradCoord.xy) / uSettingGrad.r; - let colorSrc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5)); + let d0 = in.vGradCoord.xy - uSettingGrad.settings.xy; + let d1 = uSettingGrad.settings.xy - uSettingGrad.focal.xy; + let r0 = uSettingGrad.settings.z; + let rd = uSettingGrad.focal.z - uSettingGrad.settings.z; + let a = 1.0*dot(d1, d1) - 1.0*rd*rd; + let b = 2.0*dot(d0, d1) - 2.0*r0*rd; + let c = 1.0*dot(d0, d0) - 1.0*r0*r0; + let t = (-b + sqrt(b*b - 4*a*c))/(2*a); + let colorSrc = textureSample(uTextureGrad, uSamplerGrad, vec2f(1.0 - t, 0.5)); let colorDst = textureSample(uTextureDst, uSamplerDst, in.vScrCoord.xy); // fill fragment data var data: FragData; diff --git a/src/renderer/wg_engine/tvgWgShaderTypes.cpp b/src/renderer/wg_engine/tvgWgShaderTypes.cpp index 56438606..6177063b 100755 --- a/src/renderer/wg_engine/tvgWgShaderTypes.cpp +++ b/src/renderer/wg_engine/tvgWgShaderTypes.cpp @@ -132,7 +132,7 @@ void WgShaderTypeGradient::update(const RadialGradient* radialGradient) auto stopCnt = radialGradient->colorStops(&stops); updateTexData(stops, stopCnt); // update base points - radialGradient->radial(&settings[2], &settings[3], &settings[0]); + radialGradient->radial(&settings[0], &settings[1], &settings[2], &settings[4], &settings[5], &settings[6]); }; diff --git a/src/renderer/wg_engine/tvgWgShaderTypes.h b/src/renderer/wg_engine/tvgWgShaderTypes.h index eddfc056..d0341a83 100755 --- a/src/renderer/wg_engine/tvgWgShaderTypes.h +++ b/src/renderer/wg_engine/tvgWgShaderTypes.h @@ -65,7 +65,7 @@ struct WgShaderTypeSolidColor #define WG_TEXTURE_GRADIENT_SIZE 512 struct WgShaderTypeGradient { - float settings[4]{}; + float settings[4+4]{}; // WGSL: struct GradSettings { settings: vec4f, focal: vec4f; transform: mat4f }; uint8_t texData[WG_TEXTURE_GRADIENT_SIZE * 4]; void update(const LinearGradient* linearGradient);