accumulator blur
This commit is contained in:
@@ -176,6 +176,7 @@ function compile_group(node, ctx, target, target_size, parent_target, parent_siz
|
||||
// Apply effects if any
|
||||
if (node.effects) {
|
||||
for (var effect of node.effects) {
|
||||
effect._node_id = node.name || `node_${ctx.target_counter}`
|
||||
target = compile_effect(effect, ctx, target, target_size)
|
||||
}
|
||||
}
|
||||
@@ -308,6 +309,10 @@ function compile_effect(effect, ctx, input_target, target_size) {
|
||||
return compile_blur_effect(effect, ctx, input_target, target_size)
|
||||
}
|
||||
|
||||
if (effect_type == 'accumulator') {
|
||||
return compile_accumulator_effect(effect, ctx, input_target, target_size)
|
||||
}
|
||||
|
||||
return input_target
|
||||
}
|
||||
|
||||
@@ -444,6 +449,46 @@ function compile_blur_effect(effect, ctx, input_target, target_size) {
|
||||
return src
|
||||
}
|
||||
|
||||
// Compile accumulator effect (motion blur)
|
||||
function compile_accumulator_effect(effect, ctx, input_target, target_size) {
|
||||
var decay = effect.decay != null ? effect.decay : 0.9
|
||||
var node_id = effect._node_id || ctx.target_counter++
|
||||
|
||||
// Create persistent targets for ping-ponging
|
||||
// We use stable keys based on node_id to ensure they persist across frames in the backend
|
||||
var accum_prev_key = `accum_prev_${node_id}`
|
||||
var accum_curr_key = `accum_curr_${node_id}`
|
||||
|
||||
var accum_prev = {type: 'target', key: accum_prev_key, width: target_size.width, height: target_size.height, persistent: true}
|
||||
var accum_curr = {type: 'target', key: accum_curr_key, width: target_size.width, height: target_size.height, persistent: true}
|
||||
|
||||
// Register them in the plan so the backend knows to create them
|
||||
ctx.targets[accum_prev_key] = {width: target_size.width, height: target_size.height, name: accum_prev_key, persistent: true}
|
||||
ctx.targets[accum_curr_key] = {width: target_size.width, height: target_size.height, name: accum_curr_key, persistent: true}
|
||||
|
||||
// Accumulation pass: curr = max(input, prev * decay)
|
||||
ctx.passes.push({
|
||||
type: 'shader_pass',
|
||||
shader: 'accumulator',
|
||||
input: input_target,
|
||||
extra_inputs: [accum_prev],
|
||||
output: accum_curr,
|
||||
uniforms: {decay: decay}
|
||||
})
|
||||
|
||||
// Feedback pass: copy curr back to prev for next frame
|
||||
ctx.passes.push({
|
||||
type: 'composite',
|
||||
source: accum_curr,
|
||||
dest: accum_prev,
|
||||
source_size: target_size,
|
||||
dest_size: target_size,
|
||||
presentation: 'disabled'
|
||||
})
|
||||
|
||||
return accum_curr
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// HELPERS
|
||||
// ========================================================================
|
||||
@@ -600,11 +645,18 @@ function execute_pass(pass, renderers, backend, resolve_target) {
|
||||
case 'shader_pass':
|
||||
var input = resolve_target(pass.input)
|
||||
var output = resolve_target(pass.output)
|
||||
var extra_inputs = []
|
||||
if (pass.extra_inputs) {
|
||||
for (var t of pass.extra_inputs) {
|
||||
extra_inputs.push(resolve_target(t))
|
||||
}
|
||||
}
|
||||
commands.push({
|
||||
cmd: 'shader_pass',
|
||||
shader: pass.shader,
|
||||
input: input,
|
||||
output: output,
|
||||
extra_inputs: extra_inputs,
|
||||
uniforms: pass.uniforms
|
||||
})
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user