Add debugging notes
This commit is contained in:
parent
81526052f2
commit
6cef5a35b2
1 changed files with 161 additions and 0 deletions
161
docs/debug/air-color-corruption.md
Normal file
161
docs/debug/air-color-corruption.md
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
air cell corruption debug log
|
||||||
|
=============================
|
||||||
|
|
||||||
|
problem
|
||||||
|
-------
|
||||||
|
air cells (materialId=0) in the world render target get corrupted to
|
||||||
|
materialId=255 after ~10 simulation frames. this causes air to render
|
||||||
|
as BLACK instead of any intended color, because the material color
|
||||||
|
lookup texture has no entry at index 255 (returns all zeros).
|
||||||
|
|
||||||
|
the original request was to change air from black to light blue.
|
||||||
|
the shader change is trivial but has no effect because the materialId
|
||||||
|
is wrong — the shader's `materialId == MAT_AIR` branch never fires.
|
||||||
|
|
||||||
|
|
||||||
|
what we confirmed
|
||||||
|
-----------------
|
||||||
|
1. init data is correct: air cells = [0,0,0,0], sand cells = [1,0,0,0]
|
||||||
|
(sync readback immediately after generateSideViewWorld + copyTextureToTexture)
|
||||||
|
|
||||||
|
2. frame 0 is clean: every render pass in the pipeline produces [0,0,0,0]
|
||||||
|
for an air cell at top-center (px=512, py=1023). checked after each:
|
||||||
|
- sandPhysicsRT: [0,0,0,0]
|
||||||
|
- worldBlurredRT: [0,0,0,0]
|
||||||
|
- antsDiscreteRT: [0,0,0,0]
|
||||||
|
- worldRT OUTPUT: [0,0,0,0]
|
||||||
|
|
||||||
|
3. by frame 10, worldRT INPUT (read before sandPhysics) = [255,0,0,0]
|
||||||
|
meaning the corruption enters between frame 9's worldCompute output
|
||||||
|
(which passed the check) and frame 10's sandPhysics input
|
||||||
|
|
||||||
|
4. renderToScreen runs between those frames (the sim loop does ~1 step
|
||||||
|
per rAF, then calls renderToScreen). so the corruption window is
|
||||||
|
during renderToScreen or between renderToScreen and the next sim step.
|
||||||
|
|
||||||
|
5. the screen shader IS being used for the full viewport (confirmed by
|
||||||
|
outputting solid blue — entire screen turned blue)
|
||||||
|
|
||||||
|
6. MAT_AIR define is correctly 0 (logged from ScreenScene constructor)
|
||||||
|
|
||||||
|
7. the shader source reaching the material IS the correct file
|
||||||
|
(first 200 chars logged and verified)
|
||||||
|
|
||||||
|
|
||||||
|
what we ruled out
|
||||||
|
-----------------
|
||||||
|
- shader not loading: confirmed via all-blue test and console.debug of source
|
||||||
|
- material color lookup texture: registry has correct values, texture
|
||||||
|
generation code (generateColorData) is straightforward
|
||||||
|
- texture filtering: all render targets use NearestFilter
|
||||||
|
- sand physics: passes through materialId unchanged for non-swapping cells
|
||||||
|
- worldBlur: outputs s0.x (material ID) unchanged
|
||||||
|
- worldCompute (world.frag): preserves materialId from input, only changes
|
||||||
|
it for deposits (depositMatId > 0) or cell clears (discreteAnts.z == 1)
|
||||||
|
- draw.frag: preserves materialId unless actively painting (drawMode >= 0)
|
||||||
|
- vite HMR: shaders load as raw strings at construction, HMR doesn't
|
||||||
|
reconstruct ShaderMaterial. confirmed shader changes take effect after
|
||||||
|
full dev server restart
|
||||||
|
- copyFramebufferToTexture: disabled it, corruption still happened at
|
||||||
|
frame 10. the copy was suspected because it writes to worldRT.texture
|
||||||
|
while that texture may still be bound from DrawScene's tWorld uniform.
|
||||||
|
BUT disabling it did not fix the issue. (this call still needs a proper
|
||||||
|
fix — either use a render pass copy or unbind the texture first)
|
||||||
|
|
||||||
|
|
||||||
|
what we have NOT tested
|
||||||
|
-----------------------
|
||||||
|
- whether the corruption happens without renderToScreen at all (skip it
|
||||||
|
entirely — won't see anything on screen but could log worldRT state)
|
||||||
|
- whether ColonyStats.update (readRenderTargetPixels on antTarget) has
|
||||||
|
side effects that corrupt worldRT. it changes the bound render target.
|
||||||
|
- whether the draw scene render itself corrupts worldRT via some WebGL
|
||||||
|
state leak (even though it writes to worldRenderTargetCopy, maybe
|
||||||
|
binding worldRT.texture as tWorld uniform causes a side effect)
|
||||||
|
- a minimal repro: disable ALL passes except sandPhysics + worldBlur +
|
||||||
|
worldCompute and see if corruption still happens (isolate whether
|
||||||
|
ant passes or screen passes introduce it)
|
||||||
|
- reading worldRT between renderToScreen and the next renderSimulation
|
||||||
|
(requires readback in the rAF callback, after renderToScreen returns)
|
||||||
|
- whether THREE.js 0.173 has known issues with Float32 render targets
|
||||||
|
and copyFramebufferToTexture / readRenderTargetPixels
|
||||||
|
|
||||||
|
|
||||||
|
render pipeline (per frame)
|
||||||
|
---------------------------
|
||||||
|
in renderSimulation():
|
||||||
|
1. sandPhysics: reads worldRT -> writes sandPhysicsRT
|
||||||
|
2. worldBlur: reads sandPhysicsRT -> writes worldBlurredRT
|
||||||
|
3. antsPresence: cleared
|
||||||
|
4. antsCompute: reads worldBlurredRT + antsPresenceRT -> writes antsComputeTarget (MRT)
|
||||||
|
5. antsDiscretize: reads antsComputeTarget -> writes antsDiscreteRT (NOT cleared per frame!)
|
||||||
|
6. worldCompute: reads worldBlurredRT + antsDiscreteRT -> writes worldRT
|
||||||
|
7. ColonyStats.update: readRenderTargetPixels on antsComputeTarget (CPU readback)
|
||||||
|
|
||||||
|
in renderToScreen():
|
||||||
|
8. drawScene: reads worldRT (tWorld) -> writes worldRenderTargetCopy
|
||||||
|
9. copyFramebufferToTexture: copies worldRenderTargetCopy framebuffer -> worldRT.texture
|
||||||
|
(CURRENTLY DISABLED in local changes)
|
||||||
|
10. screenScene: reads worldRenderTargetCopy (map) -> writes to canvas (null target)
|
||||||
|
|
||||||
|
worldRT is the persistent world state. it feeds back into itself:
|
||||||
|
worldRT -> sandPhysics -> worldBlur -> worldCompute -> worldRT
|
||||||
|
|
||||||
|
|
||||||
|
current local changes (uncommitted)
|
||||||
|
------------------------------------
|
||||||
|
1. src/shaders/screenWorld.frag:
|
||||||
|
- air background color changed from white vec3(1,1,1) to light blue vec3(0.53, 0.81, 0.92)
|
||||||
|
- this change works correctly IF materialId is 0 for air cells
|
||||||
|
- also: the committed version has stale debug grayscale code from a previous session
|
||||||
|
that needs to be cleaned up
|
||||||
|
|
||||||
|
2. src/Renderer.ts:
|
||||||
|
- copyFramebufferToTexture disabled (replaced with comment)
|
||||||
|
- minor whitespace change
|
||||||
|
- both should be reverted when the real fix is found
|
||||||
|
|
||||||
|
3. src/scenes/ScreenScene.ts:
|
||||||
|
- groundDefines extracted to variable (cosmetic, from debug session)
|
||||||
|
|
||||||
|
4. src/materials/registry.ts:
|
||||||
|
- air color changed from [0,0,0,0] to [0.53,0.81,0.92,1.0]
|
||||||
|
- this was an early attempt that doesn't matter since the shader
|
||||||
|
hardcodes the air branch (doesn't use the lookup for air)
|
||||||
|
|
||||||
|
|
||||||
|
key file locations
|
||||||
|
------------------
|
||||||
|
- world init: src/WorldInit.ts (generateSideViewWorld)
|
||||||
|
- render pipeline: src/Renderer.ts (renderSimulation + renderToScreen)
|
||||||
|
- world texture format: RGBA Float32, R=materialId, G=scentToHome, B=scentToFood, A=repellent
|
||||||
|
- screen shader: src/shaders/screenWorld.frag
|
||||||
|
- world compute: src/shaders/world.frag
|
||||||
|
- sand physics: src/shaders/sandPhysics.frag
|
||||||
|
- pheromone blur: src/shaders/worldBlur.frag
|
||||||
|
- draw shader: src/shaders/draw.frag
|
||||||
|
- material constants: src/constants.ts (MAT_AIR=0 through MAT_HOME=5)
|
||||||
|
- material registry: src/materials/registry.ts
|
||||||
|
- color lookup texture gen: src/materials/lookupTexture.ts
|
||||||
|
|
||||||
|
|
||||||
|
suggested next steps
|
||||||
|
--------------------
|
||||||
|
1. try disabling renderToScreen entirely and adding a single
|
||||||
|
console.debug readback of worldRT after 20 frames. if worldRT stays
|
||||||
|
[0,0,0,0] for air, the corruption is caused by renderToScreen or
|
||||||
|
something it triggers.
|
||||||
|
|
||||||
|
2. if step 1 still shows corruption, try disabling the ant passes
|
||||||
|
(antsCompute, antsDiscretize, antsPresence clear) and see if the
|
||||||
|
corruption disappears. the world pipeline without ants is just
|
||||||
|
sandPhysics -> worldBlur -> worldCompute, which should be a no-op
|
||||||
|
for air cells.
|
||||||
|
|
||||||
|
3. if step 2 still shows corruption, the issue might be in sandPhysics
|
||||||
|
(Margolus block CA) or worldCompute. try disabling each individually.
|
||||||
|
|
||||||
|
4. check THREE.js 0.173 changelog/issues for Float32 render target bugs.
|
||||||
|
|
||||||
|
5. consider adding a "sanitizer" pass that clamps materialId to [0,5]
|
||||||
|
at the start of each frame as a workaround while debugging.
|
||||||
Loading…
Reference in a new issue