Particles self shadowing

Hello folks! I was trying to get some shadows added to my particles system - I was trying to replicate a similar effect to what Edan Kwan does in this experiment but, alas, was unsuccessful (the demo is quite old and you can see the code here).
You can see an (unfortunately) messy example of what I have so far here, using custom depth and distance shaders. I can see some shadows being cast and received by the particles, but it somehow seems like these have no depth nor self-shadowing.
In short my question is: is it possible for particles to cast and receive the shadow of other particles? if so, what am I doing wrong?

In your example, I see a curlicue shape, but no particles. I am using the latest version of Chrome.

I’ve updated the codesandbox to be more clearly particles! you should be seeing the individual particles that produce that shape now

I see the particles now. They create the shape. And the shape does create a shadow.
But I can’t tell whether the points are casting a shadow on each other (which is, I believe, your question).
I would suggest changing the color of the particles to white (like in the experiment) and changing the color of the base to a slightly different color (so you can still see the particles against the base.)

Currently, particles use a defined material (PointsMaterial). But the developers are making some significant changes to three.js to allow use of WebGPU. So even if the current version of three.js does not allow self-shadows of points, future versions might.

I have a few simple particle emitters. I will see if I can get them to throw and receive some shadows.

2 Likes

Thank you so much for looking into this! I’ve updated the demo to use pointLight rather than spotLight, updated the customDistanceMaterial and changed the color to plain white. I can still see the shadow being cast onto the floor (although, it’s cutting off the shadow for some reason that I can’t quite understand) and it’s getting the whole particle system in shadow, without receiving any shadow within the particles. It looks like the angle from which the shadow is coming from is not exactly the angle the light is being cast from either

I was able to put together a simple example with a box and a points emitter over a flat plane.
The box casts a shadow on the flat plane. The points do not cast or receive a shadow.
The console log for Chrome states that
THREE.Material: ‘castShadow’ is not a property of THREE.PointsMaterial.
THREE.Material: ‘receiveShadow’ is not a property of THREE.PointsMaterial.

The GitHub page for the example you cited states that it “uses the the new particles which invented by Simo Santavirta @simppafi”. The page also says that the example was inspired by David Li’s Flow experiment. (David Li wrote the shaders for the wave generator that I spents several months updating.) The particles on David Li’s Flow experiment are also self-shading and cast shadows. But David Li does not use three.js. So it is possible that you could find a particle shader and adapt it for use with three.js (just like Jeremy Bouny did to make David Li’s wave generator work with three.js).

Or it is possible that this change to PointsMaterial will be made as part of the changeover to WebGPU.

Another option would be to make the particles using instancing. There are several examples of instancing in the three.js examples. I haven’t tried it, but I expect that you can use materials that are capable of casting and receiving shadows.

Now that I see that PointsMaterial does not cast or receive shadows I would also like to see that improvement. So post a demo if you figure out how to do it!

I’ve recently come back to this and got a sort of example running here. Unfortunately it’s not what I was hoping for (also doesn’t look very nice, definitely needs some tweaking): I’m calculating the shadows based on the dot product between the normal of the particle and the position of the light and blending in the distance from the camera

I’d expect that this is not what you look for. I’m sorry about this.

In any case, here are 500k particles (instanced), with lighting and self-shadowing. You need a good GPU for this, because the code is genuinely barbaric. The number of particles is set in line 59.

https://codepen.io/boytchev/full/xxQvLpv

image

2 Likes

that’s awesome! thank you for making this. unfortunately i was looking to get a similar result with particles rather than instanced meshes

This looks great and works fine on my 5 year old GPU!
Based on your experience with instancing, do you think instancing could be used to create more cloudlike objects, like the “ghosts” in the OP?

I have never made clouds with instanced meshes. Maybe it is best to try it and see what happens.

I think I’ve got it working using points and custom shaders with the threejs shader chunk! Will share some code as soon i properly clean it up

1 Like