OverviewFilesCommitsIssuesDocsReleasesPeers

ifsrenderer-linux commits / 58fef08

Stop replaying the same samples when the camera keeps moving
"if you go into flymode it moves around a bit doesn't hold its place." The seed is constant and `dispatch_cnt` was reset to 0 by every invalidation. Both feed the kernel's hash, so a restarted accumulation drew the IDENTICAL sample set every time. Orbiting hides it - you stop, and it accumulates - but fly mode moves continuously, so every frame invalidated and redrew the same sparse constellation of points, which then slid across the screen with the camera. That is not the fractal failing to hold its place; it is one fixed sample set being reprojected. Split into two counters. `dispatch_count` is monotonic and feeds the RNG, so no two dispatches ever share hash inputs. `since_reset` is zeroed by invalidate() and only decides when to re-seed the point state. Continuous motion now shows fresh noise that resolves when you stop, instead of a moving lattice. `iterations` reports since_reset, which is what is actually on screen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
58fef088c485db893ba832e6de9bc0cf8fbb7307
by plankatron <fleeky@gmail.com> · 2026-08-16T23:24:07.000Z

Changed files (1) +13 -4

blender/ifs_viewport.py +13 -4
……@@ -139,7 +139,11 @@ class Session:
139139 self.width = 0
140140 self.height = 0
141141 self.last_view = None
142 self.dispatch_count = 0
142 # Two counters, deliberately. `dispatch_cnt` goes into the kernel's hash
143 # and must NEVER repeat, or a restarted accumulation replays the identical
144 # sample set. `since_reset` decides when to re-seed the point state.
145 self.dispatch_count = 0 # monotonic, feeds the RNG
146 self.since_reset = 0 # zeroed by invalidate()
143147 self.frames = 0
144148
145149 self.kernel, self.drain, self.library = ifs_render._build_shaders(
……@@ -297,7 +301,11 @@ class Session:
297301 self.histogram.clear(format='UINT', value=(0, 0, 0, 0))
298302 self.accum.clear(format='FLOAT', value=(0.0, 0.0, 0.0, 0.0))
299303 self.state.clear(format='FLOAT', value=(0.0, 0.0, 0.0, 0.0))
300 self.dispatch_count = 0
304 # dispatch_count is NOT reset: it is hash input, and rewinding it makes
305 # every restart draw the same points. Under continuous camera motion that
306 # is a fixed constellation sliding across the screen rather than the
307 # fractal - which is what fly mode looked like.
308 self.since_reset = 0
301309
302310 # -------------------------------------------------------------------- camera
303311
……@@ -369,7 +377,7 @@ class Session:
369377 frame = gpu.types.GPUUniformBuf(ifs_host.pack_frame(
370378 seed=0x9E3779B9, width=self.width, height=self.height,
371379 dispatch_cnt=self.dispatch_count,
372 reset_points_state=1 if self.dispatch_count == 0 else 0,
380 reset_points_state=1 if self.since_reset == 0 else 0,
373381 invocation_iters=self.iters_per_frame))
374382
375383 self.kernel.bind()
……@@ -382,6 +390,7 @@ class Session:
382390 self.kernel.uniform_block(name, ubo)
383391 gpu.compute.dispatch(self.kernel, ifs_render.WORKGROUPS, 1, 1)
384392 self.dispatch_count += 1
393 self.since_reset += 1
385394
386395 self.drain.bind()
387396 self.drain.image('histogram_img', self.histogram)
……@@ -420,7 +429,7 @@ class Session:
420429
421430 @property
422431 def iterations(self):
423 return self.dispatch_count * self.iters_per_frame * ifs_render.INVOCATIONS
432 return self.since_reset * self.iters_per_frame * ifs_render.INVOCATIONS
424433
425434
426435def start(document_path, iters_per_frame=400):