Reputation: 1693
I am trying to vary the opacity of particles as a function of their distance from a plane.
This issue describes my problem, and the answer a year ago was essentially "you can't". Opacity is apparently a parameter of a material, not an element, and hence individual particle opacity is not possible.
Has anything changed, is there any way I could achieve this? If individual particle colouring is possible, I imagine this isn't out of reach.
Cheers
Upvotes: 17
Views: 15534
Reputation: 104783
EDIT - This answer shows how to set per-point opacity using a custom ShaderMaterial
. See https://stackoverflow.com/a/67892506/1461008 for an approach using PointsMaterial
.
ParticleSystem
has been renamed to PointCloud
and then to Points
.
Yes, you can create a Point Cloud and vary the alpha value of each particle's color dynamically.
In three.js, you can do this by setting the Point Cloud's material to be a ShaderMaterial
having an attribute equal to the desired alpha value for each particle.
If ShaderMaterials
, vertex shaders and fragment shaders are new to you, here is a really simple Fiddle that implements a Point Cloud with dynamic alphas: https://jsfiddle.net/9Lvrnpwc/.
EDIT: Updated fiddle
three.js r.148
Upvotes: 32
Reputation: 1618
Not sure why, but proposed solution didn't work for me. I used somewhat tricky shading to make points round and blurry at edges. So the corners of points were supposed to be transparent, but they appeared black: http://jsfiddle.net/5kz64ero/1/
Relevant part of my fragment shader:
// Distance from 0.0 to 0.5 from the center of the point
float d = distance(gl_PointCoord, vec2(0.5, 0.5));
// Applying sigmoid to smoothen the edge
float opacity = 1.0 / (1.0 + exp(16.0 * (d - 0.25)));
gl_FragColor = vec4(opacity * vColor, opacity);
I figured that traditionally this is solved by depth-sorting (with farthest points coming first), and I found some evidence that some older implementations of ParticleSystem
in Three contained sortParticles
attribute. But it's not there anymore. And in my case sorting would really involve redoing that every time camera position changes. Instead I set depthWrite: false
and it seems to solve the issue.
The result: http://jsfiddle.net/5kz64ero/6/
Upvotes: 0