Skip to content

Conversation

@WestLangley
Copy link
Collaborator

@WestLangley WestLangley commented Aug 12, 2025

Fixes #31179.
Fixes #31353.

The goal here is to match WebGLRenderer's output using PointsMaterial.

@WestLangley WestLangley added this to the r180 milestone Aug 12, 2025
@github-actions
Copy link

github-actions bot commented Aug 12, 2025

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 338.9
79.1
338.9
79.1
+0 B
+0 B
WebGPU 570.29
157.49
570.33
157.5
+37 B
+17 B
WebGPU Nodes 568.9
157.24
568.94
157.26
+37 B
+18 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Before After Diff
WebGL 470.64
113.87
470.64
113.87
+0 B
+0 B
WebGPU 643.13
173.9
643.16
173.92
+40 B
+25 B
WebGPU Nodes 597.34
163.12
597.34
163.12
+0 B
+0 B

@Mugen87 Mugen87 merged commit 0188ec2 into mrdoob:dev Aug 12, 2025
9 checks passed
@WestLangley WestLangley deleted the dev-points_node_material branch August 12, 2025 11:18
@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 18, 2025

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 20, 2025

@WestLangley Can you please revisit this change? webgpu_lights_custom is obviously broken. The example code should generate random points inside a conceptual cube shape.

Depending on the camera, the point cloud looks now distorted. This becomes more clear if you remove the custom lighting model:

regression-pointcloud.mov

This is clearly a regression. If not fixed, we have to revert the PR before the r180 release.

@WestLangley
Copy link
Collaborator Author

This PR ads an extra scale factor ( by DPR * canvas_height ) to mirror the implementation in WebGLRenderer.

//

Here are the use cases that, as of now, must be supported:

sprite = new THREE.Sprite( new THREE.SpriteNodeMaterial() );

instancedPoints = new THREE.Sprite( new THREE.PointsNodeMaterial( { positionNode: instancedBufferAttribute( positionAttribute ) } ) );

pointCloud = new THREE.Points( new THREE.BufferGeometry(), new THREE.PointsNodeMaterial() );

It is the third use case that is the problem.

When PointsNodeMaterial is used as the material for Sprite, the points have a size that is honored.

When the same material is used as the material for Points, size is ignored.

//

@sunag @Mugen87 Can you please help with the architecture here? PointsNodeMaterial and SpriteNodeMaterial are closely coupled by WebGPURenderer.

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 21, 2025

This PR ads an extra scale factor ( by DPR * canvas_height ) to mirror the implementation in WebGLRenderer

Unfortunately, the implementation is not correct.

The scale factor 0.5 * height * dpr must be a uniform and not inlined. Besides, you can't extract the DPR in setupVertex() since you miss dynamic changes to the DPR set via renderer.setPixelRatio().

The distortion from the video comes from the fact that the new scaled point size is incorrectly used in subsequent shader code for point primitives.

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 21, 2025

@sunag Can we implement two setupVertex() methods? One setupVertexPoints() and setupVertexSprites()? We then call the correct method for the render primitive in setupVertex(). This would make it easier to integrate @WestLangley's code changes.

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 21, 2025

@WestLangley The scale uniform from sprites.glsl.js can be implemented like so:

const _size = /*@__PURE__*/ new Vector2();

const scale = /*@__PURE__*/ uniform( 1 ).onFrameUpdate( function ( { renderer } ) {

	const dpr = renderer.getPixelRatio();
	const size = renderer.getSize( _size );

	this.value = 0.5 * size.y * dpr;

} );

If you need DPR as a uniform, I suggest we enhance ScreenNode and add ScreenNode.DPR. You can then write the current DPR in ScreenNode.update() into the uniform.

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 21, 2025

#31702 attempts to provide a fix.

@WestLangley
Copy link
Collaborator Author

@Mugen87 Thank you for your help!

@sunag
Copy link
Collaborator

sunag commented Aug 21, 2025

@sunag Can we implement two setupVertex() methods? One setupVertexPoints() and setupVertexSprites()? We then call the correct method for the render primitive in setupVertex(). This would make it easier to integrate @WestLangley's code changes.

The idea was great. Thank you too! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PointNodeMaterial: Size Differs from WebGL PointsMaterial PointsNodeMaterial - Size Change on DPR

3 participants