mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +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
|
} else // normal
|
||||||
if (blendType == WgPipelineBlendType::Normal) {
|
if (blendType == WgPipelineBlendType::Normal) {
|
||||||
blendState.color.operation = WGPUBlendOperation_Add;
|
blendState.color.operation = WGPUBlendOperation_Add;
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
blendState.color.srcFactor = WGPUBlendFactor_One;
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
||||||
} else // add
|
} else // add
|
||||||
if (blendType == WgPipelineBlendType::Add) {
|
if (blendType == WgPipelineBlendType::Add) {
|
||||||
|
@ -627,9 +627,7 @@ WGPUBlendState WgRenderPipeline::makeBlendState(WgPipelineBlendType blendType)
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_One;
|
blendState.color.srcFactor = WGPUBlendFactor_One;
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_One;
|
blendState.color.dstFactor = WGPUBlendFactor_One;
|
||||||
}
|
}
|
||||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
blendState.alpha = blendState.color;
|
||||||
blendState.alpha.srcFactor = WGPUBlendFactor_SrcAlpha;
|
|
||||||
blendState.alpha.dstFactor = WGPUBlendFactor_Zero;
|
|
||||||
return blendState;
|
return blendState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -291,7 +291,8 @@ void WgPipelineBlend::initialize(WGPUDevice device)
|
||||||
WGPUBindGroupLayout bindGroupLayouts[] = {
|
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||||
WgBindGroupTextureStorageRgba::getLayout(device),
|
WgBindGroupTextureStorageRgba::getLayout(device),
|
||||||
WgBindGroupTextureStorageRgba::getLayout(device),
|
WgBindGroupTextureStorageRgba::getLayout(device),
|
||||||
WgBindGroupBlendMethod::getLayout(device)
|
WgBindGroupBlendMethod::getLayout(device),
|
||||||
|
WgBindGroupOpacity::getLayout(device)
|
||||||
};
|
};
|
||||||
|
|
||||||
// sheder source and labels
|
// sheder source and labels
|
||||||
|
|
|
@ -132,12 +132,13 @@ struct WgPipelineClear: public WgComputePipeline
|
||||||
struct WgPipelineBlend: public WgComputePipeline
|
struct WgPipelineBlend: public WgComputePipeline
|
||||||
{
|
{
|
||||||
void initialize(WGPUDevice device) override;
|
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);
|
set(encoder);
|
||||||
groupTexSrc.set(encoder, 0);
|
groupTexSrc.set(encoder, 0);
|
||||||
groupTexDst.set(encoder, 1);
|
groupTexDst.set(encoder, 1);
|
||||||
blendMethod.set(encoder, 2);
|
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(commandEncoder);
|
||||||
assert(targetSrc);
|
assert(targetSrc);
|
||||||
WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder);
|
WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder);
|
||||||
mPipelines->computeBlend.use(computePassEncoder, targetSrc->bindGroupTexStorageRgba, bindGroupTexStorageRgba, *blendMethod);
|
mPipelines->computeBlend.use(computePassEncoder, targetSrc->bindGroupTexStorageRgba, bindGroupTexStorageRgba, *blendMethod, *opacity);
|
||||||
dispatchWorkgroups(computePassEncoder);
|
dispatchWorkgroups(computePassEncoder);
|
||||||
endComputePass(computePassEncoder);
|
endComputePass(computePassEncoder);
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
void renderPicture(WgContext& context, WgRenderDataPicture* renderData, WgPipelineBlendType blendType);
|
void renderPicture(WgContext& context, WgRenderDataPicture* renderData, WgPipelineBlendType blendType);
|
||||||
|
|
||||||
void clear(WGPUCommandEncoder commandEncoder);
|
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 compose(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetMsk, WgBindGroupCompositeMethod* composeMethod, WgBindGroupOpacity* opacity);
|
||||||
void composeBlend(
|
void composeBlend(
|
||||||
WgContext& context,
|
WgContext& context,
|
||||||
|
|
|
@ -168,7 +168,8 @@ bool WgRenderer::renderShape(RenderData data)
|
||||||
mRenderTarget.endRenderPass();
|
mRenderTarget.endRenderPass();
|
||||||
// blend shape with current render storage
|
// blend shape with current render storage
|
||||||
WgBindGroupBlendMethod* blendMethod = mBlendMethodPool.allocate(mContext, mBlendMethod);
|
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
|
// restore current render pass
|
||||||
renderStorage->beginRenderPass(mCommandEncoder, false);
|
renderStorage->beginRenderPass(mCommandEncoder, false);
|
||||||
}
|
}
|
||||||
|
@ -194,7 +195,8 @@ bool WgRenderer::renderImage(RenderData data)
|
||||||
mRenderTarget.endRenderPass();
|
mRenderTarget.endRenderPass();
|
||||||
// blend shape with current render storage
|
// blend shape with current render storage
|
||||||
WgBindGroupBlendMethod* blendMethod = mBlendMethodPool.allocate(mContext, mBlendMethod);
|
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
|
// restore current render pass
|
||||||
renderStorage->beginRenderPass(mCommandEncoder, false);
|
renderStorage->beginRenderPass(mCommandEncoder, false);
|
||||||
}
|
}
|
||||||
|
@ -290,7 +292,7 @@ bool WgRenderer::sync()
|
||||||
|
|
||||||
mContext.executeCommandEncoder(commandEncoder);
|
mContext.executeCommandEncoder(commandEncoder);
|
||||||
wgpuCommandEncoderRelease(commandEncoder);
|
wgpuCommandEncoderRelease(commandEncoder);
|
||||||
|
|
||||||
wgpuSurfacePresent(mContext.surface);
|
wgpuSurfacePresent(mContext.surface);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -367,7 +369,8 @@ bool WgRenderer::endComposite(TVG_UNUSED Compositor* cmp)
|
||||||
|
|
||||||
// blent scene to current render storage
|
// blent scene to current render storage
|
||||||
WgBindGroupBlendMethod* blendMethod = mBlendMethodPool.allocate(mContext, comp->blendMethod);
|
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
|
// back render targets to the pool
|
||||||
mRenderStoragePool.free(mContext, renderStorageSrc);
|
mRenderStoragePool.free(mContext, renderStorageSrc);
|
||||||
|
|
|
@ -101,7 +101,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
// get color
|
// get color
|
||||||
color = uSolidColor;
|
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 */
|
if (format == 1u) { /* FMT_ARGB8888 */
|
||||||
result = color.bgra;
|
result = color.bgra;
|
||||||
} else if (format == 2u) { /* FMT_ABGR8888S */
|
} else if (format == 2u) { /* FMT_ABGR8888S */
|
||||||
result = vec4(color.rgb * color.a, color.a);
|
result = color.rgba;
|
||||||
} else if (format == 3u) { /* FMT_ARGB8888S */
|
} 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(0) @binding(0) var imageSrc : texture_storage_2d<rgba8unorm, read_write>;
|
||||||
@group(1) @binding(0) var imageDst : 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(2) @binding(0) var<uniform> blendMethod : u32;
|
||||||
|
@group(3) @binding(0) var<uniform> opacity : f32;
|
||||||
|
|
||||||
@compute @workgroup_size(8, 8)
|
@compute @workgroup_size(8, 8)
|
||||||
fn cs_main( @builtin(global_invocation_id) id: vec3u) {
|
fn cs_main( @builtin(global_invocation_id) id: vec3u) {
|
||||||
let texSize = textureDimensions(imageSrc);
|
let texSize = textureDimensions(imageSrc);
|
||||||
if ((id.x >= texSize.x) || (id.y >= texSize.y)) { return; };
|
if ((id.x >= texSize.x) || (id.y >= texSize.y)) { return; };
|
||||||
|
|
||||||
let srcColor = textureLoad(imageSrc, id.xy);
|
let colorSrc = textureLoad(imageSrc, id.xy);
|
||||||
if (srcColor.a == 0.0) { return; };
|
let colorDst = textureLoad(imageDst, id.xy);
|
||||||
let dstColor = textureLoad(imageDst, id.xy);
|
|
||||||
|
|
||||||
let Sa: f32 = srcColor.a;
|
let So: f32 = opacity;
|
||||||
let Da: f32 = dstColor.a;
|
let Sa: f32 = colorSrc.a;
|
||||||
let S: vec3f = srcColor.xyz;
|
let Da: f32 = colorDst.a;
|
||||||
let D: vec3f = dstColor.xyz;
|
let S: vec4f = colorSrc;
|
||||||
let One: vec3f = vec3(1.0);
|
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 {
|
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); }
|
/* Add */ case 1u: { color = (S + D); }
|
||||||
/* Screen */ case 2u: { color = (S + D) - (S * D); }
|
/* Screen */ case 2u: { color = (S + D) - (S * D); }
|
||||||
/* Multiply */ case 3u: { color = (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; }
|
/* ColorBurn */ case 11u: { color = One - (One - D) / S; }
|
||||||
/* HardLight */ case 12u: { color = (Sa * Da) - 2.0 * (Da - S) * (Sa - D); }
|
/* HardLight */ case 12u: { color = (Sa * Da) - 2.0 * (Da - S) * (Sa - D); }
|
||||||
/* SoftLight */ case 13u: { color = (One - 2 * S) * (D * D) + (2 * S * 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; };
|
if ((length(colorSrc) == 0.0) || (length(colorMsk) == 0.0)) { return; };
|
||||||
let colorDst = textureLoad(imageDst, id.xy);
|
let colorDst = textureLoad(imageDst, id.xy);
|
||||||
|
|
||||||
var color: vec3f = colorSrc.xyz;
|
var result: vec3f = colorSrc.xyz;
|
||||||
var alpha: f32 = colorMsk.a;
|
var alpha: f32 = colorMsk.a;
|
||||||
let luma: f32 = dot(colorMsk.xyz, vec3f(0.299, 0.587, 0.114));
|
let luma: f32 = dot(colorMsk.xyz, vec3f(0.299, 0.587, 0.114));
|
||||||
switch composeMethod {
|
switch composeMethod {
|
||||||
/* None */ case 0u: { color = colorSrc.xyz; }
|
/* None */ case 0u: { result = colorSrc.xyz; }
|
||||||
/* ClipPath */ case 1u: { if (colorMsk.a == 0) { alpha = 0.0; }; }
|
/* ClipPath */ case 1u: { if (colorMsk.a == 0) { alpha = 0.0; }; }
|
||||||
/* AlphaMask */ case 2u: { color = colorSrc.xyz; alpha = colorSrc.a * colorMsk.a; }
|
/* AlphaMask */ case 2u: { result = colorSrc.xyz; alpha = colorSrc.a * colorMsk.a; }
|
||||||
/* InvAlphaMask */ case 3u: { color = colorSrc.xyz; alpha = colorSrc.a * (1.0 - colorMsk.a); }
|
/* InvAlphaMask */ case 3u: { result = colorSrc.xyz; alpha = colorSrc.a * (1.0 - colorMsk.a); }
|
||||||
/* LumaMask */ case 4u: { color = colorSrc.xyz; alpha = colorSrc.a * luma; }
|
/* LumaMask */ case 4u: { result = colorSrc.xyz; alpha = colorSrc.a * luma; }
|
||||||
/* InvLumaMask */ case 5u: { color = colorSrc.xyz; alpha = colorSrc.a * (1.0 - luma); }
|
/* InvLumaMask */ case 5u: { result = colorSrc.xyz; alpha = colorSrc.a * (1.0 - luma); }
|
||||||
/* AddMask */ case 6u: { color = colorSrc.xyz * colorSrc.a + colorMsk.xyz * (1.0 - colorSrc.a); }
|
/* AddMask */ case 6u: { result = colorSrc.xyz * colorSrc.a + colorMsk.xyz * (1.0 - colorSrc.a); }
|
||||||
/* SubtractMask */ case 7u: { color = 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: { color = colorSrc.xyz * min(colorSrc.a, colorMsk.a); }
|
/* IntersectMask */ case 8u: { result = colorSrc.xyz * min(colorSrc.a, colorMsk.a); }
|
||||||
/* DifferenceMask */ case 9u: { color = abs(colorMsk.xyz - colorSrc.xyz * (1.0 - colorMsk.a)); }
|
/* DifferenceMask */ case 9u: { result = abs(colorMsk.xyz - colorSrc.xyz * (1.0 - colorMsk.a)); }
|
||||||
default: { color = colorSrc.xyz; }
|
default: { result = colorSrc.xyz; }
|
||||||
}
|
}
|
||||||
|
|
||||||
let S: vec3f = color.xyz;
|
let So: f32 = opacity;
|
||||||
let D: vec3f = colorDst.xyz;
|
|
||||||
let Sa: f32 = alpha;
|
let Sa: f32 = alpha;
|
||||||
let Da: f32 = colorDst.a;
|
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 {
|
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); }
|
/* Add */ case 1u: { color = (S + D); }
|
||||||
/* Screen */ case 2u: { color = (S + D) - (S * D); }
|
/* Screen */ case 2u: { color = (S + D) - (S * D); }
|
||||||
/* Multiply */ case 3u: { color = (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; }
|
/* ColorBurn */ case 11u: { color = One - (One - D) / S; }
|
||||||
/* HardLight */ case 12u: { color = (Sa * Da) - 2.0 * (Da - S) * (Sa - D); }
|
/* HardLight */ case 12u: { color = (Sa * Da) - 2.0 * (Da - S) * (Sa - D); }
|
||||||
/* SoftLight */ case 13u: { color = (One - 2 * S) * (D * D) + (2 * S * 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