Scaling particles based on camera distance

Hi all,

I’m currently working on a modified version of the GPUParticleSystem at https://threejs.org/examples/#webgl_gpu_particle_system along with the version from https://github.com/joshmarinacci/webxr-experiments/blob/master/particles/GPUParticleSystem2.js. Everything works nicely apart from the fact that the points retain a uniform screen-size independent from the distance of the camera. Meaning that If I get really close the particles, they’re tiny and if I’m far away, the system becomes huge and very laggy.

i.e. close by -
chrome_2019-01-21_17-51-29

Far away:
chrome_2019-01-21_17-51-56

I’m not completely sure it’s possible as far as my knowledge with THREE.Points goes, but maybe someone else can offer insight?
My goal is that when I’m far away from the system, the sprites retain the same size in world-space as they do when close by.

Current GPUParticleSystem code:
https://hastebin.com/momeviniwu.js

I think you are looking for an effect called “size attenuation”. Check out the following demo to see the effect.

https://threejs.org/examples/webgl_points_billboards.html

THREE.PointsMaterial provides a property in order to activate/deactivate size attenuation. I have not studied your code in detail but I guess you could use a similar approach like the built-in material.

4 Likes

Aaah I knew of Size Attenuation from PointsMaterial, not sure why I didn’t think of copying that.

I presume that mvPosition in the shader can be substituted for cameraPosition? Because otherwise, mvPosition is not a property in the shader/program.

However, I just tried this and it seems to make the particles super small, and changing the scale or even multiplying scale by a constant, doesn’t seem to change the size at all.
I tried commenting out any other shadercode that changes gl_PointSize, too.

No, mvPosition represent the vertex position in view space (model-view-position). It’s usually calculated like so:

vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

Ah okay, thanks! Still a bit new to shaders :slight_smile:
I just tried this and it works partially! The size no longer acts weird depending on camera distance, however it now acts weird depending on a mix of camera distance and viewing angle :sweat_smile:

When looking down:
chrome_2019-01-22_10-45-07
When looking up:

hey @Mugen87, under this link

there a scale variable. Where does it come from?
I tried to look in ShaderChunk ‘begin_vertex’ and ‘project_vertex’ but can’t find it there.
I am digging the topic as i’d like to learn how to calculate sizeAttenuation in custom ShaderMaterial, where each vertex has own size (as attribute with BufferGeometry). Points are equally distanced from camera z position, but there is ‘zoom’ behaviour that uses both camera z and camera fov. I would like to keep the points sizes ‘proportionally’ scaled depending on zoom. Many thanks for a hint.

scale is a float uniform which is declared at the top of points_vert.glsl.js.

1 Like

And this is what scale is:

Reference: https://stackoverflow.com/a/30548534/4045502