wg_engine: wrong gradient transformation fixed

issue: https://github.com/thorvg/thorvg/issues/2620
This commit is contained in:
Sergii Liebodkin 2024-09-13 07:36:21 +03:00 committed by GitHub
parent 91a538d1f2
commit 7a6a89cf26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 49 additions and 10 deletions

View file

@ -45,6 +45,19 @@ WGPUBindGroup WgBindGroupLayouts::createBindGroupTexSampledBuff1Un(WGPUSampler s
}
WGPUBindGroup WgBindGroupLayouts::createBindGroupTexSampledBuff2Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff0, WGPUBuffer buff1)
{
const WGPUBindGroupEntry bindGroupEntrys[] = {
{ .binding = 0, .sampler = sampler },
{ .binding = 1, .textureView = texView },
{ .binding = 2, .buffer = buff0, .size = wgpuBufferGetSize(buff0) },
{ .binding = 3, .buffer = buff1, .size = wgpuBufferGetSize(buff1) }
};
const WGPUBindGroupDescriptor bindGroupDesc { .layout = layoutTexSampledBuff2Un, .entryCount = 4, .entries = bindGroupEntrys };
return wgpuDeviceCreateBindGroup(device, &bindGroupDesc);
}
WGPUBindGroup WgBindGroupLayouts::createBindGroupStrorage1WO(WGPUTextureView texView)
{
const WGPUBindGroupEntry bindGroupEntrys[] = {
@ -164,6 +177,18 @@ void WgBindGroupLayouts::initialize(WgContext& context)
assert(layoutTexSampledBuff1Un);
}
{ // bind group layout tex sampled with buffer uniforms
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
{ .binding = 0, .visibility = visibility_frag, .sampler = sampler },
{ .binding = 1, .visibility = visibility_frag, .texture = texture },
{ .binding = 2, .visibility = visibility_vert, .buffer = bufferUniform },
{ .binding = 3, .visibility = visibility_vert, .buffer = bufferUniform }
};
const WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc { .entryCount = 4, .entries = bindGroupLayoutEntries };
layoutTexSampledBuff2Un = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
assert(layoutTexSampledBuff1Un);
}
{ // bind group layout tex storage 1 WO
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
{ .binding = 0, .visibility = visibility_frag, .storageTexture = storageTextureWO }

View file

@ -31,6 +31,7 @@ private:
public:
WGPUBindGroupLayout layoutTexSampled{};
WGPUBindGroupLayout layoutTexSampledBuff1Un{};
WGPUBindGroupLayout layoutTexSampledBuff2Un{};
WGPUBindGroupLayout layoutTexStrorage1WO{};
WGPUBindGroupLayout layoutTexStrorage1RO{};
WGPUBindGroupLayout layoutTexStrorage2RO{};
@ -41,6 +42,7 @@ public:
public:
WGPUBindGroup createBindGroupTexSampled(WGPUSampler sampler, WGPUTextureView texView);
WGPUBindGroup createBindGroupTexSampledBuff1Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff);
WGPUBindGroup createBindGroupTexSampledBuff2Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff0, WGPUBuffer buff1);
WGPUBindGroup createBindGroupStrorage1WO(WGPUTextureView texView);
WGPUBindGroup createBindGroupStrorage1RO(WGPUTextureView texView);
WGPUBindGroup createBindGroupStrorage2RO(WGPUTextureView texView0, WGPUTextureView texView1);

View file

@ -176,7 +176,7 @@ void WgPipelines::initialize(WgContext& context)
const WGPUBindGroupLayout bindGroupLayoutsGradient[] = {
layouts.layoutBuffer1Un,
layouts.layoutBuffer2Un,
layouts.layoutTexSampledBuff1Un
layouts.layoutTexSampledBuff2Un
};
const WGPUBindGroupLayout bindGroupLayoutsImage[] = {
layouts.layoutBuffer1Un,

View file

@ -212,6 +212,13 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_
// setup fill properties
if ((flags & (RenderUpdateFlag::Gradient)) && fill) {
rasterType = WgRenderRasterType::Gradient;
// get gradient transfrom matrix
Matrix fillTransform = fill->transform();
Matrix invFillTransform;
WgShaderTypeMat4x4f gradientTrans; // identity by default
if (inverse(&fillTransform, &invFillTransform))
gradientTrans.update(invFillTransform);
// get gradient rasterisation settings
WgShaderTypeGradient gradient;
if (fill->type() == Type::LinearGradient) {
gradient.update((LinearGradient*)fill);
@ -222,8 +229,9 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_
}
// update gpu assets
bool bufferGradientSettingsChanged = context.allocateBufferUniform(bufferGroupGradient, &gradient.settings, sizeof(gradient.settings));
bool bufferGradientTransformChanged = context.allocateBufferUniform(bufferGroupTransfromGrad, &gradientTrans.mat, sizeof(gradientTrans.mat));
bool textureGradientChanged = context.allocateTexture(texGradient, WG_TEXTURE_GRADIENT_SIZE, 1, WGPUTextureFormat_RGBA8Unorm, gradient.texData);
if (bufferGradientSettingsChanged || textureGradientChanged) {
if (bufferGradientSettingsChanged || textureGradientChanged || bufferGradientTransformChanged) {
// update texture view
context.releaseTextureView(texViewGradient);
texViewGradient = context.createTextureView(texGradient);
@ -233,8 +241,8 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_
if (fill->spread() == FillSpread::Repeat) sampler = context.samplerLinearRepeat;
// update bind group
context.pipelines->layouts.releaseBindGroup(bindGroupGradient);
bindGroupGradient = context.pipelines->layouts.createBindGroupTexSampledBuff1Un(
sampler, texViewGradient, bufferGroupGradient);
bindGroupGradient = context.pipelines->layouts.createBindGroupTexSampledBuff2Un(
sampler, texViewGradient, bufferGroupGradient, bufferGroupTransfromGrad);
}
skip = false;
} else if ((flags & (RenderUpdateFlag::Color)) && !fill) {
@ -256,6 +264,7 @@ void WgRenderSettings::release(WgContext& context)
context.pipelines->layouts.releaseBindGroup(bindGroupGradient);
context.releaseBuffer(bufferGroupSolid);
context.releaseBuffer(bufferGroupGradient);
context.releaseBuffer(bufferGroupTransfromGrad);
context.releaseTexture(texGradient);
context.releaseTextureView(texViewGradient);
};

View file

@ -82,6 +82,7 @@ struct WgRenderSettings
WGPUTexture texGradient{};
WGPUTextureView texViewGradient{};
WGPUBuffer bufferGroupGradient{};
WGPUBuffer bufferGroupTransfromGrad{};
WGPUBindGroup bindGroupGradient{};
WgRenderSettingsType fillType{};
WgRenderRasterType rasterType{};

View file

@ -84,7 +84,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) vScreenCoord : vec2f };
struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec4f };
// uniforms
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
@ -93,18 +93,19 @@ struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenC
@group(2) @binding(0) var uSamplerGrad : sampler;
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
@group(2) @binding(2) var<uniform> uSettingGrad : vec4f;
@group(2) @binding(3) var<uniform> uTransformGrad : mat4x4f;
@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
var out: VertexOutput;
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
out.vScreenCoord = in.position.xy;
out.vScreenCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let pos = in.vScreenCoord;
let pos = in.vScreenCoord.xy;
let st = uSettingGrad.xy;
let ed = uSettingGrad.zw;
let ba = ed - st;
@ -121,7 +122,7 @@ 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) vScreenCoord : vec2f };
struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec4f };
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
@ -129,18 +130,19 @@ struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenC
@group(2) @binding(0) var uSamplerGrad : sampler;
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
@group(2) @binding(2) var<uniform> uSettingGrad : vec4f;
@group(2) @binding(3) var<uniform> uTransformGrad : mat4x4f;
@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
var out: VertexOutput;
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
out.vScreenCoord = in.position.xy;
out.vScreenCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let t: f32 = distance(uSettingGrad.zw, in.vScreenCoord) / uSettingGrad.r;
let t: f32 = distance(uSettingGrad.zw, in.vScreenCoord.xy) / uSettingGrad.r;
let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5));
let So = uBlendSettings.a;
return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);