Repository navigation
Conversation
… engine patch (PRD-775) Ports the 0.185.1 patch onto 0.187.0 by 3-way merge plus per-hunk intent review, regenerates the bundle hunks from the r187 tag (stock build == npm, byte for byte), drops the PRD-269 0.185.1 predecessor migration, and overrides three for published packages that still pin 0.185.1. Patch specs are reworked in the next commit.
…h null previous matrices (PRD-775) - @types/three 0.187: TextureNode instead of ReturnType<typeof texture>, QuadMesh(material). - getShadowMaterial(light) moved onto the shadow node (same per-light cache). - WorldCells and TerrainTiles call super.dispose() (r186 Object3D.dispose dispatches the dispose event). - PCFSoftShadowFilter is gone upstream (r186), so its shared-render-group case is dropped. - BatchedMesh._previousMatricesTexture is null when absent in r187; the velocity lane checks != null. - Patch: PMREM async face 5 restores mipmapsAutoUpdate (source mips), every draw step runs again.
…hunk classification (PRD-775) - classifyFile only shifts later hunks by hunks already patched on disk. Adding stock hunks' line deltas put the preferred position halfway between two identical generated blocks in build/three.tsl.js and threw TN_THREE_PATCH_INVALID (ambiguous hunk location). - PRD-269 migration tests deleted with the migration; clean install, idempotence and tamper refusal kept. PMREM async tests retargeted to the r187 cube-camera generator. - Patch: ShadowFilterNode keeps the stock trailing newline (the hunk was a no-op). - Scaffold hashes recomputed for the new patch bytes.
…haviours the rebase lost (PRD-775) Stubs: renderer/backend/builder stubs gain the r187 members they now need. Patch (from arm E's findings, each with its failing spec): - WebGPUBackend._validateTransientDepth accepts r187's read-only 'let VERTEX_nodeConst' vertex chain (private depth never validated: 38 tests). - PRD-566 morph-layout term restored in the WebGPU pipeline key (getGeometryCacheKey( false )). - NodeMaterialObserver asks firstInitialization before the settled recompute registers the object. - Geometries.updateAttribute re-uploads a buffer written again within one render call. Engine: GpuFrameObservation detects r187's self-resolving full query pool (index restart).
….0 (PRD-775) 95 of 205 goldens changed, each with an upstream reason (PR body): r187 ACES fit, r186/r187 physical lighting energy rewrite, r187 PMREM cube targets, r187 TRAA, r187 LatheGeometry normal. The owned engine's ACES fit follows r187 (output ramp worst 0/255). Native pins, catalog and ABI header name 0.187.0; the reference page serves addons from the pinned tree by path.
…on the native host (PRD-775) r187's WebGPUBackend asks 'currentPass instanceof GPURenderBundleEncoder' on every draw; the native host never defined the class, so the native smoke died with a ReferenceError (pump-silence 2 red -> 13/13). The class answers by a brand createRenderBundleEncoder puts on its encoders. Spec pins name 0.187.0.
…n three 0.187.0 (PRD-775) r187 frees a node-owned storage attribute on its own dispose event, no longer through the geometry's render objects; the probe's five instancedArray buffers stayed live after detach (spec red -> 166/166). The spec follows r187's Geometries(backend, attributes, info) and initGeometry(geometry).
…(PRD-775) Ports r186/r187 PhysicalLightingModel: one shared DFG sample, multiScatteringCompensation on direct specular, (1 - F) on direct diffuse, the dielectric energy loss on indirect diffuse, BRDF_GGX's 0.045 alpha floor and getRoughness's 0.045 floor, and clearcoatRoughnessMap reading green. BRDF_GGX_Multiscatter is gone as upstream. lit_reference worst 9 -> 1 (13.1% -> 0% channels over one level); 74/74 renderer cases.
…hree 0.187.0 (PRD-775) r187's NodeBuilder skips the shared bind-group cache only when renderer._bindings is undefined, but an uninitialised Renderer holds null there; building a node before init crashed (8 spec files). The patch checks != null. temporal-aa's builder stub answers r187's getNodeFromHash.
… import and references (PRD-775) - Ray.intersectTriangle is r187's watertight test (Ray.js:538-662); raycaster 9 differ -> 0. - LatheGeometry normalizes the last point's normal (r187 LatheGeometry.js:106). - The graph importer no longer lowers a void Fn loop body twice: r187 dropped VarNode intents. - The TSL corpus harness reads r187's Fn()() and assignable shapes; corpus text byte-identical. - References regenerated from 0.187.0; post tests name r187. Lockfile carries the new patch hash. native-engine label: 33 -> 8 failures (all render/post work in progress).
…ee 0.187.0 (PRD-775) - TRAA: jitter wraps at 32 (r187 TRAANode.js:330); the history seeds from the resolved frame's own beauty (r187 :390-400), not a pre-scene copy. traa_history 0.928 -> pass, history_cut 0.968 -> pass. - Shadows: r187 removed PCFSoftShadowFilter and rewrites PCFSoftShadowMap to PCFShadowMap (Renderer.js:1031); radiusScaled is per-axis. shadows-directional-soft 0.080 -> pass. - MaterialX: mx_hash_int_3 applies mx_bjmix as r187 emits it. materialx-noise 0.404 -> pass. - frame_slab light-flip fingerprint 2037 -> 2034 after the r187 lighting port.
…specs follow three 0.187.0 (PRD-775) r187 TRAANode hands its view-offset pair to the pipeline through OnBefore/OnAfterRenderPipeline lists and only while renderPipelineState.viewOffsetOwner is free; the starter's provider now claims that owner and removes only its own entries. Specs: real setup-stage builders, r187 renderer.debug, compute via builder.compute, ReferenceBufferAttributeNode, cached size nodes. 10 spec files red -> green.
…ropping their frame (PRD-775) The patch's queue-fenced PMREM bake binds PMREMNode's placeholder CubeTexture while the bake runs. Textures.getSize gave an image-less cube texture one layer, the cube view asked for six, and Dawn dropped the whole command buffer: every environment-lit scene drew black until the bake landed, and six 0.187.0 goldens were recorded black. getSize now allocates 1x1x6 (as _getDefaultCubeTextureGPU does), and Renderer.whenEnvironmentReady() lets a single-frame caller draw the settled look. The reference capture now fails closed on a WebGPU validation error (TN_FIXTURE_RENDER_GPU_ERROR) and on a one-colour frame (TN_FIXTURE_RENDER_UNIFORM_FRAME). Re-recorded only the six goldens; the pmrem-hdr-equirect frame is byte-identical to stock r187. test:reference --check: 205 fixtures, 0 problems.
… shipped sRGB exponent (PRD-775) GTAO: r187 GTAONode.js:405-584 (projectionDepth, background discard, integer STEPS, clip-space quadratic march, IGN+rand jitter, new horizon update, isValidSample); the engine's reachPx Unreal search stays verbatim. Bloom: r187 BloomNode.js:519-531 merges adjacent Gaussian taps into one bilinear fetch. Output: three's build ships pow(0.41666), not 1/2.4 (three.tsl.js:9382); the engine now matches it. tsl-post-ao-raw, tsl-post-bloom (0 px), live-parameters, template-high and reflector-plane (0 px) pass; gtao_screen_reach's world-radius control arm re-measured. native-engine: 523/526.
…noiseNode (PRD-775) three inlines DenoiseNode into its consumer (r187 DenoiseNode.js:16,163-259), so the bilateral result is never stored as half float. The engine stored every post pass as RGBA16F; on a flat AO field the f16 rounding is one-sided and flipped 11.5% of tsl-post-ao one 8-bit level down (dE 0.060 vs gate 0.04). The denoise pass now targets RGBA32Float when float32-filterable exists (RGBA16F fallback otherwise). tsl-post-ao dE 0.0044. native-engine: 524/526; left: render_pmrem, render_data_textures (native PMREM port in flight).
…D-775) three 0.187 replaced the cubeUV atlas with a cube render target whose mips carry the roughness steps, so the engine's generator and sampler move together (report-K's change list, items 1-6 and 8): - the generator bakes a HalfFloat source cube from the equirect with four subpixel taps, grows its full mip chain, then filters mip lod at lodToRoughness(lod, maxLod): 256-sample GGX VNDF with filtered importance sampling and the per-lod lodBias for the sharp levels, and the 16px integration tail over three faces for the last three (MIN_SIZE 256, LOD_MIN 3, so a 64x32 sky bakes a 256 cube with six mips where r185 made a 16px atlas). - every pass draws one face of one mip of the cube: the equirect conversion and the bake read the direction through CubeCamera's view matrix, so the cubes they write are the cubes three writes, and the source mip chain downsamples in the row order a face is stored in. - the sampler's PMREM is a cube texture again: roughnessToMip = maxLod*r*(2-r) replaces the piecewise cubeUV ramp, textureCubeUV and its 16px filter tiles are gone, and the render-target Y flip goes with the atlas. - frame-pumped packets, the environment validation, the pmremRotation and environmentRotation wiring are unchanged; one packet is one face now, so the budget counts fragments x samples per face. Every environment fixture matches three 0.187.0: native_engine_render_pmrem, _render_data_textures, and the hand-run sky-equirect, material-ao-environment, pbr-grid-envmap and pmrem-texture cases.
…case (PRD-775) sky-equirect, material-ao-environment and pbr-grid-envmap light a scene from three's PMREM, and no ctest case ran them, so the r185-to-r187 PMREM port had no gate on the two of them that sample an environment through a material. One case, native_engine_render_environment, runs all three against their 0.187.0 goldens. Comments that still described the PMREM as a cubeUV atlas follow the code.
…urce (PRD-775) three reads the PMREM target and the source cube through the same LinearMipmapLinearFilter clamp sampler, so the bake needs one cube sampler plus the 2D one the mip chain blits with.
… engine ports (PRD-775)
PRD-775 ARM A — three.js patch port 0.185.1 → 0.187.0Files: the 15 in this arm's list. Every hunk of src/materials/nodes/manager/NodeMaterialObserver.js
src/nodes/accessors/Batch.js
File now equals stock r187. src/nodes/accessors/Instance.js
src/nodes/accessors/Skinning.js
src/nodes/accessors/TextureNode.js
src/nodes/accessors/TextureSizeNode.js
src/nodes/accessors/VelocityNode.js
src/nodes/core/NodeBuilder.js
src/nodes/display/PassNode.js
src/nodes/lighting/PointShadowNode.js
src/nodes/lighting/ShadowFilterNode.js
src/nodes/pmrem/PMREMNode.js
src/objects/BatchedMesh.js
examples/jsm/tsl/display/SMAANode.js
examples/jsm/tsl/display/SSRNode.js
Doubts, ranked by risk
ARM DONE |
Ledger — ARM B (0.185.1 → 0.187.0 port of the ThreeNative patch)Repo: Notes that apply to every row:
src/renderers/common/Bindings.js
src/renderers/common/Geometries.js
src/renderers/common/RenderContexts.js
src/renderers/common/RenderObject.js
src/renderers/common/RenderObjects.js
Result: this file is byte-identical to stock r187 ( src/renderers/common/RenderPipeline.js
src/renderers/common/Renderer.js
src/renderers/common/Textures.js
src/renderers/common/extras/PMREMGenerator.js
src/renderers/common/nodes/NodeManager.js
src/renderers/webgpu/WebGPUBackend.js
src/renderers/webgpu/nodes/WGSLNodeBuilder.js
src/renderers/webgpu/utils/WebGPUAttributeUtils.js
src/renderers/webgpu/utils/WebGPUBindingUtils.js
src/renderers/webgpu/utils/WebGPUPipelineUtils.js
src/renderers/webgpu/utils/WebGPUTextureUtils.js
Doubts, ranked by risk
|
…o temporalAA.ts stays under 200 lines (PRD-775) looks.spec keeps every generated render file under 200 lines; the r187 claim had grown temporalAA.ts to 209. Same behaviour: claim() checks the r187 render pipeline state, takes the view offset, captures the context.
CI run 41233630666 test-unit (3/4): quality-json found a new biome-ignore at temp-node.ts:111. A shorthand property from a local const carries the same export without the waiver.
…op merge CI run 41233630666 budgets: src/, tests/, cmake/ and four more rows drifted past tolerance 5.
…n it (PRD-775) CI run 41240800887 template-nonvisual (sailing): after exactly 7200 ticks the game's elapsed sum is 119.99999999999447 s, so wind = 1 - elapsed / 120 is 4.6e-14, not 0, and the status is still sailing. Develop passed only because startup frames stepped the game first (its held warm-up timed out at 5 s; on three 0.187 it completes in 2.7 s), a margin that depended on load. The scenario now waits 7260 ticks, one second past the boundary. Local, CI flags (webgpu, headed): both float scenarios pass, exit 0.
AC-8 ticked: paired presented p95 on Midway and the stress lab, web and native desktop, NEUTRAL; native:verify:desktop exit 0; CI run 41248394799 on c38dcde adds no red develop does not have (linux-arm64 and its receipt, and the adventure, collectathon, rain and shooter timeouts fail the same on develop runs 41230261223 and 41226270743). The PRD moves to done/ and the Unreal port status regenerates.
Run 41248394799 on c38dcde still fails linux-arm64, its coverage receipt and the adventure, collectathon, rain and shooter timeouts. They fail on develop too, but AC-8 asks for a green board, so the box stays open until they pass.
…loor to three 0.187 Develop's eac89e9 floors the patched PMREMGenerator's fence budget at a 256 cube's heaviest face. The same floor goes into three@0.187.0.patch (src and both builds). On r187 it changes no fence: PMREMGenerator's MIN_SIZE is 256 there, so a 64 x 32 sky already bakes a 256 cube, the same bake as a 1k sky (15 fences in the stub). pmrem-fence.spec.ts gains the renderer fields r187 reads (coordinateSystem, xr, reversedDepthBuffer) and asserts that equivalence instead of the r185 one-fence case. Scaffold hashes re-pinned for develop's sky changes and the new patch bytes.
# Conflicts: # packages/core/patches/three@0.185.1-prd269-upgrade.patch
…evice runs nobody did
# Conflicts: # docs/verification/native-coverage-2026-08-28.md # packages/create-threenative/templates/adventure/package.json # packages/create-threenative/templates/collectathon/package.json # packages/create-threenative/templates/kart/package.json # packages/create-threenative/templates/minimal/package.json # packages/create-threenative/templates/platformer/package.json # packages/physics/package.json
…oves mid-walk The guard walks packages/ while starter-post-bundle creates and removes temporary projects there, so a vanished file failed the guard with ENOENT. The asset cook's pending journal also stays out of the example's tree, beside the outputs it names.
…not two seconds in A fixed two-second delay ran past the reveal once startup got faster: the first 1.6 s the player saw drew 731 calls where 104 hold. Readiness follows a sustained window of real frames, which is what the delay stood in for. PRD-775 also stops claiming a fix for a parity row that flips on one head.
# Conflicts: # packages/create-threenative/templates/adventure/package.json # packages/create-threenative/templates/collectathon/package.json # packages/create-threenative/templates/kart/package.json # packages/create-threenative/templates/minimal/package.json # packages/create-threenative/templates/platformer/package.json # packages/physics/package.json
…eline, not the launch The engine's frame series starts when compilation settles, before readiness, so a scenario also answered for frames behind the loading cover, where the shooter's resident pools draw on purpose. The baseline is read from a running game, and a host without frame numbers keeps its whole series.
… settle on readiness
What is this PR about?
It moves every package, template and generated game from three.js 0.185.1 to 0.187.0. It rebases the ThreeNative patch onto the new release, and ports the r186/r187 rendering changes into the owned C++ engine, so the native and Wasm engines still match three pixel for pixel.
Why does it matter?
Games get two releases of upstream fixes, such as the ACES fit, energy-conserving lighting, PMREM cube targets and watertight raycasts. The patch stops drifting from three.js.
Done
✅ Phase 1 (AC-1..3): every pin is on 0.187.0, the patch is rebased hunk by hunk (ledger below), and the installer specs are green.
✅ Native engine ported to r187: lighting (shared DFG, multi-scatter, roughness floors), TRAA, PCF shadows, MaterialX noise, the watertight ray, the lathe normal, GTAO, the bloom tap merge, the sRGB build exponent, the denoise precision and the PMREM cube mip chain.
ctest -L native-engine: 527/527.✅ Real bugs found and fixed on the way:
GPURenderBundleEncoder(ReferenceErroron every draw).renderer.init()crashed.Renderer.js:3238), so ocean and fluid warm-ups compiled nothing.✅ Dropped the patch's transient output-depth hunk (−1208 patch lines). r187 draws the RenderPipeline output at one sample, so the hunk never ran.
✅
pnpm parityvs develop6bf21eab2: every red this PR added is fixed. The remaining reds (web temporal-aa-scaled, -lifecycle, vfx-spawn-requests, realism-velocity; desktop temporal-aa, realism-*) fail the same way on develop.✅ The reference capture now fails closed on a WebGPU validation error and on a single-colour frame.
✅ Phases 2 and 3 (AC-4..8): typecheck, lint, unit tests and parity are green; every kit plays from spawn; the visual judge returns NEUTRAL or IMPROVEMENT for every template; perf is NEUTRAL on web and native desktop.
✅ AC-8 perf (presented p95, 5 paired runs per lane, RTX 2080): Midway web 16.68 / 16.68 ms, stress lab web 16.68 / 16.68 ms, Midway desktop 18.15 / 18.41 ms (+1.4 %), stress lab desktop 17.07 / 17.02 ms. All NEUTRAL.
pnpm native:verify:desktopexit 0.✅ CI on
c38dcde74(run 41248394799): 65 jobs pass. CI found 7 PR-only reds over three runs, all fixed:8ee2f524b)3d50a8dbc)8e7cc84ee), the native census (4826787f1), and sailing's wind check on its 120 s float boundary (c38dcde74)CI
✅ Full board green on
c3f5598f7, run 41288721287, first attempt: 89 jobs pass, 4 skipped by design (queue-watchand 3 V8 payload jobs),ci-requiredpass.✅ The two commits after that run,
2c6954d6eand4f0a79fad, change only the PRD and the generated Unreal port status files.pnpm check:docspasses on both, and the review lane passes on4f0a79fadwithci-required.✅ The shooter engine-cost timeout on run 41265123694 is hosted-VM variance, not r187. A local paired 1260-frame row (4 cores, SwiftShader) read 843 and 1464 s on base against 799 and 861 s on r187. The leg took 17 minutes in the green run.
shooterperformancepeaks at 128 draw calls, down from 731. It still misses its frame limit at 17.9 ms (GPU). Develop misses it too, at 18.3 to 19.5 ms on the same machine.fc0a73183has no full board of its own. The full run above is on the older headc3f5598f7. The merge queue runs the board.Notes for review
gtaoRadius(action-rpg, rts, runner, shooter). The other 12 templates use the engine's reachPx search, which is unchanged.099ce70f8); RGBA32Float had cost +0.87 ms GPU on the stress lab.packages/core/src/gpu-frame-observation.tsnow wraps r187's self-resolving query pool. It is no longer read-only, so please review it.docs/PRDs/Unreal/shadows/PRD-775-virtual-shadow-pages-…(another lane). This PR's PRD is thetech-debt-code-qualityone.6bf21eab2, not this PR:native_engine_player_gpu_stages(same failure on the base build).Batch.js:78).Changed goldens (AC-5): one upstream reason each
One or more upstream causes necessarily move each frame's hash, so a group row is one reason per fixture.
diffdata: 94 fixtures differ only inrender.pngSha256; exactly one fixture differs in a number.toneMapping: "aces"— all 78 aces render fixtures, e.g.lit-render,batched-mesh,fog-*,gltf-model-*,materials-*,morph-*,nodemat-*,particles-sprite,pbr-grid-envmap,pmrem-texture,probes*,reflector-plane,screen-uv,shadows-*,skinned-*,sky-equirect,storage-attribute,texture-object,textures-data-3d,tonemap-ramp-aces,tsl-*,viewport-textures,vsm-*,fluid-particles,lights-point-spot,materialx-noisesrc/nodes/display/ToneMappingFunctions.js:69(r187):b = color*(color*0.983729 + 0.4329510) + 0.238081; r185 wascolor*(color + 0.4329510)*0.983729 + 0.238081. Upstream: r187 "Fix ACES Filmic fit denominator" #35110. Control:tonemap-ramp-acesmoved (strip 1 227→226) whiletonemap-ramp-{agx,cineon,linear,neutral,reinhard}and their fixtures did not, so the ACES curve is the only tone-curve change.gltf-model-specular,material-ao-environment,material-normal-map,material-pbr-maps,materials-bump-map,materials-force-single-pass,materials-metal-rough-maps,materials-vertex-colors,materials-vertex-node,textures-data-float,textures-data-half,textures-data-rgba8src/nodes/functions/PhysicalLightingModel.js:329(r187): direct specular is nowirradiance.mul(specularBRDF).mul(multiScatteringCompensation), replacing r185'sBRDF_GGX_Multiscatter(… f90: 1 …); indirect at:879-895. Upstream: r186 removedBRDF_GGX_Multiscatterand re-derived multi-scattering energy (#33983, #33985, #34046, #34055), r187 "share dielectric scattering in indirect lighting" #34656, "fix specular intensity in direct lighting" #34764. Every one of these 12 is lit; every non-aces fixture that did not change (alpha-test,alpha-transparency,blending-additive,gltf-model-webp,lines-basic,textures-anisotropy,textures-data-{canvas-mips,filters,wraps}) has no light and no shading material.pmrem-hdr-equirect,textures-data-equirectsrc/extras/PMREMGenerator.js(r187): the CubeUV atlas is gone, replaced byCubeCamera+ cube render targets (MIN_SIZE = 256,src/extras/PMREMGenerator.js:31) — r187 "Replace the CubeUV atlas with cube render targets" #34585, plus r186 "spiral blur" #32367 and r187 "restore minimal roughness, improve roughness ramp" #34645. Both fixtures are unlit metal spheres lit only by the environment.history-cut,traa-historyexamples/jsm/tsl/display/TRAANode.js:237(r187): the previous-depth node now samplesthis._historyRenderTarget.depthTextureinstead of its ownDepthTexture(1, 1);:330: the jitter wraps over all 32 offsets (% length) where r185 wrapped atlength - 1. Same file also drops the post-processing view-offset sync and pre-initialises its targets on resize.geometry-lathe0.035999998450279236 → 1(muzzle), 18 of 54 (partial)src/geometries/LatheGeometry.js:106(r187) addsprevNormal.normalize()before the last vertex's normal is pushed; r185 pushed it unnormalised. Upstream: r187 "Normalize the normal of the last point" #35153.Subsystem-specific changes that ride inside the groups above and are the reason a reviewer will see those rows move:
tsl-post-smaa(r186SMAANodefix/simplification #34031),tsl-post-bloom/tsl-post-template-high(r186
BloomNodeblur strategy #33923),tsl-post-ao/tsl-post-ao-raw(r186GTAONodequadratic stepping,clip-space march, banding, baked sample count #33895/#33903/#33919/#33931),
shadows-*/vsm-*(r187ShadowFilterNodePCF radius #35018 and per-shadow uniforms #35047,PointShadowNode#34899/#35186,ShadowNode#34801/#35093),screen-uv(r186ScreenNodeDPR #34186),particles-sprite(r187SpriteNodeMaterialcentre #35064),materialx-noise(r187RangeNodehash/random-order #34897/#34920),reflector-plane(r187ReflectorNodeview offset #34917, bounces #34977),lit-render-scaled/tsl-post-resized(r186PassNodepixel ratio #34453).No diff without an upstream reason. Nothing else in the corpus moved: all 97 non-render goldens except
geometry-latheare byte-identical.Re-recorded after the PMREM patch fix:
pmrem-hdr-equirect,pmrem-texture,textures-data-equirect,sky-equirect,material-ao-environmentandpbr-grid-envmapwere first recorded as solid black frames, the dropped command buffer described above. They are now real frames (1482 to 25621 colours).pmrem-hdr-equirectis byte-identical to a capture on stock r187.test:reference --check: 205 fixtures, 0 problems.Dropped patch hunks (AC-2): reason per hunk
The ledger has 153 rows: 82 kept, 33 ported and 38 dropped. The full per-hunk ledger, kept and ported rows included, is in the two PR comments below.
NodeMaterialObserver.js#3_equalfromgetGeometryData_version: 0in the same literal (src/materials/nodes/manager/NodeMaterialObserver.js:420r187) plus `geometNodeMaterialObserver.js#4_equalfromgetMaterialDatadata = { _renderId: - 1, _version: 0 }.NodeMaterialObserver.js#5materialData._equal = falsebefore a material diff returnchanged = true/materialData._version ++, which is this fix done properly.NodeMaterialObserver.js#6changed = truein thevalue.equalsbranch.NodeMaterialObserver.js#7changed = true+value.cacheVersion/value.transformtracking.NodeMaterialObserver.js#8changed = truein the else branch.NodeMaterialObserver.js#9_equal = true/else if _equal === falseearly-out so everenderObjectData.materialVersion !== materialData._versionmismatch, plus an output-targetNodeMaterialObserver.js#10geometryData._equal = false, removed-attribute branchchanged = true; continue;.NodeMaterialObserver.js#11changed = true.NodeMaterialObserver.js#12changed = true.NodeMaterialObserver.js#13changed = true.NodeMaterialObserver.js#14changed = true.NodeMaterialObserver.js#15_equal = true/else ifearly-outif ( changed === true ) geometryData._version ++;+renderObjectData.geometryVersion !== geometryData._version.Batch.js#1positionPreviousfor the motion-vector batch transformsrc/nodes/accessors/Batch.js:2imports{ positionLocal, positionPrevious }already.Batch.js#2previousMatricesTexture= `batchMesh._previousMatricesTexture ?? matgetPreviousMatricesTexture( batchMesh )creates the texture from_matricesTextureon first use (and again afterBatchedMeshdisBatch.js#3positionPreviousfrom the previous batching matrix when `needcreateBatchingMatrixNode( getPreviousMatricesTexture( batchMesh ), indirectId )→ `positionPrevious.assign( preBatch.js#4Instance.js#3instance()and track the buf_matrixBuffers, nointerleavedMatrix/interleavedColorlocals; the columns are `new InterleavedBuInstance.js#4OnBeforeFrameUpdateSkinning.js#1previousBoneMatricesData()— per-skeleton history created at the cursetupPreviousBoneData( skeleton )(r187:159-187) does the same, storing on the skeleton (previousBoneMatrices,previousBoneTexture, both deShadowFilterNode.js#2PCFShadowFilteruses the sharedmapSize/radiusconst { mapSize, radius } = getShadowUniforms( shadow );.ShadowFilterNode.js#3PCFSoftShadowFilteruses the sharedmapSizePCFSoftShadowFilterwas deleted upstream (r187src/nodes/lighting/ShadowNode.js:117keepsnull /* PCFSoftShadowMap, removed */in `_shadowFilterPMREMNode.js#6textureCubeUV/_width/_height/_maxMipwere removed upstream; r187 samples the generated cube texture directly (`thisRenderObject.js#1_sourceMaterialthis render object was validatethis.sourceMaterialVersion = this._sourceMaterial !== null ? this._sourceMaterial.version : 0;(RendeRenderObject.js#2getChainArray()must include the source material so override and non[ object, material, context, lightsNode, this._sourceMaterial ]when_sourceMaterial !== null, which is the same discriminator (oursRenderObject.js#3getGeometryCacheKey( useMorphTargetIds )— a pipeline key must not dWebGPUAttributeUtils.getVertexBufferLayoutCacheKey( renderObject )to the pipeline cache key and removed stride/offset/index from the geoRenderObjects.js#1_chainKeys[ 4 ]) so mate_overrideChainKeys(5 slots,[ null, null, null, null, null ]) used only while an override is active, with `chainKeys[ 4 ] = sourcRenderObjects.js#2RenderObjects.js#3_chainKeys[ 4 ]after the lookupchainKeys[ 4 ]only whensourceMaterial !== null, which matches its 4-vs-5 slot schemeRenderer.js#9overrideMaterial._alphaTestso the shared override material'sRenderer.js#13RenderObjectRefreshType(constants.js:1711) and_renderObjectDirectgatesFULL/SHARED/NONE(Renderer.js:4Renderer.js#14nodes.updateAfter( renderObject )after a drawNONE(if ( refreshType !== RenderObjectRefreshType.NONE ) this._nodes.updateAfter( renderObject )) andWebGPUBackend.js#11WebGPUBackend.js#12currentBindingGroups[ i ] = bindGroupGPU;WebGPUBackend.js#16utils.getStripIndexFormat( object, geometry )+this.attributeUtils.getVertexBufferLayoutCacheKey( renderObject ), wWebGPUBackend.js#20copyTextureToTexture's mipmapWGSLNodeBuilder.js#3uniformNode.name = name ? name : 'NodeBuffer_' + uniformNode.id;is gone fromgetUniformFromNode), soWebGPUTextureUtils.js#4if ( colorTextureData.texture !== undefined && colorTexture.width === width && … )andcolorTexture.image.width = width;WebGPUBackend.js#21 (transient output depth: alsoRenderer.js,RenderPipeline.js,WebGPU{Attribute,Binding,Pipeline}Utils.js)_beginTransientDepth/_finishTransientDepth/_restoreTransientDepth/_isFullTransientViewport/_validateTransientDepthand the_tnOutputOwner/_tnDepthProof/_tnUniformBytes/_tnFullTrianglefull-quad proofPRD:
docs/PRDs/done/PRD-775-upgrade-three-to-0.187.md