mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 19:44:28 +00:00
wg_engine: fix scene opacity usage
Changed blend equation to make it the same as for referenced sw renderer.
This commit is contained in:
parent
359ad22b3a
commit
21286f679d
7 changed files with 58 additions and 48 deletions
|
@ -604,7 +604,7 @@ WGPUBlendState WgRenderPipeline::makeBlendState(WgPipelineBlendType blendType)
|
|||
} else // normal
|
||||
if (blendType == WgPipelineBlendType::Normal) {
|
||||
blendState.color.operation = WGPUBlendOperation_Add;
|
||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
||||
blendState.color.srcFactor = WGPUBlendFactor_One;
|
||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
||||
} else // add
|
||||
if (blendType == WgPipelineBlendType::Add) {
|
||||
|
@ -627,9 +627,7 @@ WGPUBlendState WgRenderPipeline::makeBlendState(WgPipelineBlendType blendType)
|
|||
blendState.color.srcFactor = WGPUBlendFactor_One;
|
||||
blendState.color.dstFactor = WGPUBlendFactor_One;
|
||||
}
|
||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
||||
blendState.alpha.srcFactor = WGPUBlendFactor_SrcAlpha;
|
||||
blendState.alpha.dstFactor = WGPUBlendFactor_Zero;
|
||||
blendState.alpha = blendState.color;
|
||||
return blendState;
|
||||
}
|
||||
|
||||
|
|
|
@ -291,7 +291,8 @@ void WgPipelineBlend::initialize(WGPUDevice device)
|
|||
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||
WgBindGroupTextureStorageRgba::getLayout(device),
|
||||
WgBindGroupTextureStorageRgba::getLayout(device),
|
||||
WgBindGroupBlendMethod::getLayout(device)
|
||||
WgBindGroupBlendMethod::getLayout(device),
|
||||
WgBindGroupOpacity::getLayout(device)
|
||||
};
|
||||
|
||||
// sheder source and labels
|
||||
|
|
|
@ -132,12 +132,13 @@ struct WgPipelineClear: public WgComputePipeline
|
|||
struct WgPipelineBlend: public WgComputePipeline
|
||||
{
|
||||
void initialize(WGPUDevice device) override;
|
||||
void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorageRgba& groupTexSrc, WgBindGroupTextureStorageRgba& groupTexDst, WgBindGroupBlendMethod& blendMethod)
|
||||
void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorageRgba& groupTexSrc, WgBindGroupTextureStorageRgba& groupTexDst, WgBindGroupBlendMethod& blendMethod, WgBindGroupOpacity& groupOpacity)
|
||||
{
|
||||
set(encoder);
|
||||
groupTexSrc.set(encoder, 0);
|
||||
groupTexDst.set(encoder, 1);
|
||||
blendMethod.set(encoder, 2);
|
||||
groupOpacity.set(encoder, 3);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -173,12 +173,12 @@ void WgRenderStorage::clear(WGPUCommandEncoder commandEncoder)
|
|||
}
|
||||
|
||||
|
||||
void WgRenderStorage::blend(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc, WgBindGroupBlendMethod* blendMethod)
|
||||
void WgRenderStorage::blend(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc, WgBindGroupBlendMethod* blendMethod, WgBindGroupOpacity* opacity)
|
||||
{
|
||||
assert(commandEncoder);
|
||||
assert(targetSrc);
|
||||
WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder);
|
||||
mPipelines->computeBlend.use(computePassEncoder, targetSrc->bindGroupTexStorageRgba, bindGroupTexStorageRgba, *blendMethod);
|
||||
mPipelines->computeBlend.use(computePassEncoder, targetSrc->bindGroupTexStorageRgba, bindGroupTexStorageRgba, *blendMethod, *opacity);
|
||||
dispatchWorkgroups(computePassEncoder);
|
||||
endComputePass(computePassEncoder);
|
||||
};
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
void renderPicture(WgContext& context, WgRenderDataPicture* renderData, WgPipelineBlendType blendType);
|
||||
|
||||
void clear(WGPUCommandEncoder commandEncoder);
|
||||
void blend(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc, WgBindGroupBlendMethod* blendMethod);
|
||||
void blend(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc, WgBindGroupBlendMethod* blendMethod, WgBindGroupOpacity* opacity);
|
||||
void compose(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetMsk, WgBindGroupCompositeMethod* composeMethod, WgBindGroupOpacity* opacity);
|
||||
void composeBlend(
|
||||
WgContext& context,
|
||||
|
|
|
@ -168,7 +168,8 @@ bool WgRenderer::renderShape(RenderData data)
|
|||
mRenderTarget.endRenderPass();
|
||||
// blend shape with current render storage
|
||||
WgBindGroupBlendMethod* blendMethod = mBlendMethodPool.allocate(mContext, mBlendMethod);
|
||||
renderStorage->blend(mCommandEncoder, &mRenderTarget, blendMethod);
|
||||
WgBindGroupOpacity* opacity = mOpacityPool.allocate(mContext, 255);
|
||||
renderStorage->blend(mCommandEncoder, &mRenderTarget, blendMethod, opacity);
|
||||
// restore current render pass
|
||||
renderStorage->beginRenderPass(mCommandEncoder, false);
|
||||
}
|
||||
|
@ -194,7 +195,8 @@ bool WgRenderer::renderImage(RenderData data)
|
|||
mRenderTarget.endRenderPass();
|
||||
// blend shape with current render storage
|
||||
WgBindGroupBlendMethod* blendMethod = mBlendMethodPool.allocate(mContext, mBlendMethod);
|
||||
renderStorage->blend(mCommandEncoder, &mRenderTarget, blendMethod);
|
||||
WgBindGroupOpacity* opacity = mOpacityPool.allocate(mContext, 255);
|
||||
renderStorage->blend(mCommandEncoder, &mRenderTarget, blendMethod, opacity);
|
||||
// restore current render pass
|
||||
renderStorage->beginRenderPass(mCommandEncoder, false);
|
||||
}
|
||||
|
@ -290,7 +292,7 @@ bool WgRenderer::sync()
|
|||
|
||||
mContext.executeCommandEncoder(commandEncoder);
|
||||
wgpuCommandEncoderRelease(commandEncoder);
|
||||
|
||||
|
||||
wgpuSurfacePresent(mContext.surface);
|
||||
return true;
|
||||
}
|
||||
|
@ -367,7 +369,8 @@ bool WgRenderer::endComposite(TVG_UNUSED Compositor* cmp)
|
|||
|
||||
// blent scene to current render storage
|
||||
WgBindGroupBlendMethod* blendMethod = mBlendMethodPool.allocate(mContext, comp->blendMethod);
|
||||
mRenderStorageStack.last()->blend(mCommandEncoder, renderStorageSrc, blendMethod);
|
||||
WgBindGroupOpacity* opacity = mOpacityPool.allocate(mContext, comp->opacity);
|
||||
mRenderStorageStack.last()->blend(mCommandEncoder, renderStorageSrc, blendMethod, opacity);
|
||||
|
||||
// back render targets to the pool
|
||||
mRenderStoragePool.free(mContext, renderStorageSrc);
|
||||
|
|
|
@ -101,7 +101,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
// get color
|
||||
color = uSolidColor;
|
||||
|
||||
return vec4f(color.rgb, color.a * uBlendSettings.opacity);
|
||||
let alpha: f32 = color.a * uBlendSettings.opacity;
|
||||
return vec4f(color.rgb*alpha, alpha);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -203,7 +204,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
}
|
||||
}
|
||||
|
||||
return vec4f(color.rgb, color.a * uBlendSettings.opacity);
|
||||
let alpha: f32 = color.a * uBlendSettings.opacity;
|
||||
return vec4f(color.rgb*alpha, alpha);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -299,7 +301,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
}
|
||||
}
|
||||
|
||||
return vec4f(color.rgb, color.a * uBlendSettings.opacity);
|
||||
let alpha: f32 = color.a * uBlendSettings.opacity;
|
||||
return vec4f(color.rgb*alpha, alpha);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -351,11 +354,11 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
if (format == 1u) { /* FMT_ARGB8888 */
|
||||
result = color.bgra;
|
||||
} else if (format == 2u) { /* FMT_ABGR8888S */
|
||||
result = vec4(color.rgb * color.a, color.a);
|
||||
result = color.rgba;
|
||||
} else if (format == 3u) { /* FMT_ARGB8888S */
|
||||
result = vec4(color.bgr * color.a, color.a);
|
||||
result = color.bgra;
|
||||
}
|
||||
return vec4f(result.rgb, result.a * uBlendSettings.opacity);
|
||||
return result * uBlendSettings.opacity;
|
||||
};
|
||||
)";
|
||||
|
||||
|
@ -379,25 +382,26 @@ const char* cShaderSource_PipelineComputeBlend = R"(
|
|||
@group(0) @binding(0) var imageSrc : texture_storage_2d<rgba8unorm, read_write>;
|
||||
@group(1) @binding(0) var imageDst : texture_storage_2d<rgba8unorm, read_write>;
|
||||
@group(2) @binding(0) var<uniform> blendMethod : u32;
|
||||
@group(3) @binding(0) var<uniform> opacity : f32;
|
||||
|
||||
@compute @workgroup_size(8, 8)
|
||||
fn cs_main( @builtin(global_invocation_id) id: vec3u) {
|
||||
let texSize = textureDimensions(imageSrc);
|
||||
if ((id.x >= texSize.x) || (id.y >= texSize.y)) { return; };
|
||||
|
||||
let srcColor = textureLoad(imageSrc, id.xy);
|
||||
if (srcColor.a == 0.0) { return; };
|
||||
let dstColor = textureLoad(imageDst, id.xy);
|
||||
let colorSrc = textureLoad(imageSrc, id.xy);
|
||||
let colorDst = textureLoad(imageDst, id.xy);
|
||||
|
||||
let Sa: f32 = srcColor.a;
|
||||
let Da: f32 = dstColor.a;
|
||||
let S: vec3f = srcColor.xyz;
|
||||
let D: vec3f = dstColor.xyz;
|
||||
let One: vec3f = vec3(1.0);
|
||||
let So: f32 = opacity;
|
||||
let Sa: f32 = colorSrc.a;
|
||||
let Da: f32 = colorDst.a;
|
||||
let S: vec4f = colorSrc;
|
||||
let D: vec4f = colorDst;
|
||||
let One: vec4f = vec4(1.0);
|
||||
|
||||
var color: vec3f = vec3f(0.0, 0.0, 0.0);
|
||||
var color: vec4f = vec4f(0.0, 0.0, 0.0, 0.0);
|
||||
switch blendMethod {
|
||||
/* Normal */ case 0u: { color = (Sa * S) + (1.0 - Sa) * D; }
|
||||
/* Normal */ case 0u: { color = (S * So) + (1.0 - Sa * So) * D; }
|
||||
/* Add */ case 1u: { color = (S + D); }
|
||||
/* Screen */ case 2u: { color = (S + D) - (S * D); }
|
||||
/* Multiply */ case 3u: { color = (S * D); }
|
||||
|
@ -411,10 +415,10 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) {
|
|||
/* ColorBurn */ case 11u: { color = One - (One - D) / S; }
|
||||
/* HardLight */ case 12u: { color = (Sa * Da) - 2.0 * (Da - S) * (Sa - D); }
|
||||
/* SoftLight */ case 13u: { color = (One - 2 * S) * (D * D) + (2 * S * D); }
|
||||
default: { color = (Sa * S) + (1.0 - Sa) * D; }
|
||||
default: { color = (S * So) + (1.0 - Sa * So) * D; }
|
||||
}
|
||||
|
||||
textureStore(imageDst, id.xy, vec4f(color, Sa));
|
||||
textureStore(imageDst, id.xy, color);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -472,30 +476,33 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) {
|
|||
if ((length(colorSrc) == 0.0) || (length(colorMsk) == 0.0)) { return; };
|
||||
let colorDst = textureLoad(imageDst, id.xy);
|
||||
|
||||
var color: vec3f = colorSrc.xyz;
|
||||
var result: vec3f = colorSrc.xyz;
|
||||
var alpha: f32 = colorMsk.a;
|
||||
let luma: f32 = dot(colorMsk.xyz, vec3f(0.299, 0.587, 0.114));
|
||||
switch composeMethod {
|
||||
/* None */ case 0u: { color = colorSrc.xyz; }
|
||||
/* None */ case 0u: { result = colorSrc.xyz; }
|
||||
/* ClipPath */ case 1u: { if (colorMsk.a == 0) { alpha = 0.0; }; }
|
||||
/* AlphaMask */ case 2u: { color = colorSrc.xyz; alpha = colorSrc.a * colorMsk.a; }
|
||||
/* InvAlphaMask */ case 3u: { color = colorSrc.xyz; alpha = colorSrc.a * (1.0 - colorMsk.a); }
|
||||
/* LumaMask */ case 4u: { color = colorSrc.xyz; alpha = colorSrc.a * luma; }
|
||||
/* InvLumaMask */ case 5u: { color = colorSrc.xyz; alpha = colorSrc.a * (1.0 - luma); }
|
||||
/* AddMask */ case 6u: { color = colorSrc.xyz * colorSrc.a + colorMsk.xyz * (1.0 - colorSrc.a); }
|
||||
/* SubtractMask */ case 7u: { color = colorSrc.xyz * colorSrc.a - colorMsk.xyz * (1.0 - colorSrc.a); }
|
||||
/* IntersectMask */ case 8u: { color = colorSrc.xyz * min(colorSrc.a, colorMsk.a); }
|
||||
/* DifferenceMask */ case 9u: { color = abs(colorMsk.xyz - colorSrc.xyz * (1.0 - colorMsk.a)); }
|
||||
default: { color = colorSrc.xyz; }
|
||||
/* AlphaMask */ case 2u: { result = colorSrc.xyz; alpha = colorSrc.a * colorMsk.a; }
|
||||
/* InvAlphaMask */ case 3u: { result = colorSrc.xyz; alpha = colorSrc.a * (1.0 - colorMsk.a); }
|
||||
/* LumaMask */ case 4u: { result = colorSrc.xyz; alpha = colorSrc.a * luma; }
|
||||
/* InvLumaMask */ case 5u: { result = colorSrc.xyz; alpha = colorSrc.a * (1.0 - luma); }
|
||||
/* AddMask */ case 6u: { result = colorSrc.xyz * colorSrc.a + colorMsk.xyz * (1.0 - colorSrc.a); }
|
||||
/* SubtractMask */ case 7u: { result = colorSrc.xyz * colorSrc.a - colorMsk.xyz * (1.0 - colorSrc.a); }
|
||||
/* IntersectMask */ case 8u: { result = colorSrc.xyz * min(colorSrc.a, colorMsk.a); }
|
||||
/* DifferenceMask */ case 9u: { result = abs(colorMsk.xyz - colorSrc.xyz * (1.0 - colorMsk.a)); }
|
||||
default: { result = colorSrc.xyz; }
|
||||
}
|
||||
|
||||
let S: vec3f = color.xyz;
|
||||
let D: vec3f = colorDst.xyz;
|
||||
let So: f32 = opacity;
|
||||
let Sa: f32 = alpha;
|
||||
let Da: f32 = colorDst.a;
|
||||
let One: vec3f = vec3(1.0);
|
||||
let S: vec4f = vec4(result, alpha);
|
||||
let D: vec4f = colorDst;
|
||||
let One: vec4f = vec4(1.0);
|
||||
|
||||
var color: vec4f = vec4f(0.0, 0.0, 0.0, 0.0);
|
||||
switch blendMethod {
|
||||
/* Normal */ case 0u: { color = (Sa * S) + (1.0 - Sa) * D; }
|
||||
/* Normal */ case 0u: { color = (S * So) + (1.0 - Sa * So) * D; }
|
||||
/* Add */ case 1u: { color = (S + D); }
|
||||
/* Screen */ case 2u: { color = (S + D) - (S * D); }
|
||||
/* Multiply */ case 3u: { color = (S * D); }
|
||||
|
@ -509,10 +516,10 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) {
|
|||
/* ColorBurn */ case 11u: { color = One - (One - D) / S; }
|
||||
/* HardLight */ case 12u: { color = (Sa * Da) - 2.0 * (Da - S) * (Sa - D); }
|
||||
/* SoftLight */ case 13u: { color = (One - 2 * S) * (D * D) + (2 * S * D); }
|
||||
default: { color = (Sa * S) + (1.0 - Sa) * D; }
|
||||
default: { color = (S * So) + (1.0 - Sa * So) * D; }
|
||||
}
|
||||
|
||||
textureStore(imageDst, id.xy, vec4f(color, Sa));
|
||||
textureStore(imageDst, id.xy, color);
|
||||
}
|
||||
)";
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue