wg_engine: fix scene opacity usage

Changed blend equation to make it the same as for referenced sw renderer.
This commit is contained in:
Sergii Liebodkin 2024-07-03 07:47:08 +03:00 committed by Hermet Park
parent 359ad22b3a
commit 21286f679d
7 changed files with 58 additions and 48 deletions

View file

@ -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;
} }

View file

@ -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

View file

@ -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);
} }
}; };

View file

@ -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);
}; };

View file

@ -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,

View file

@ -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);

View file

@ -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);
} }
)"; )";