5

I would like to produce fuzzy random points (sprites like) in a 3D view. Applying a Blur command doesn't do the trick since the view is then frozen and we couldn't rotate the view anymore, and I don't want to blur the frame box too.

Here's a MWE to play with (currently, I'm using some transparency to blur slightly the particles, but the effect isn't that good!) :

particles := RandomReal[{-1, 1}, {1000, 3}]

graph := Graphics3D[{RGBColor[{0.5, 0.4, 1.0, 0.4}], PointSize -> 0.006, Point[particles]}]

Show[graph, PlotRange -> {{-1, 1}, {-1, 1}, {-1, 1}}, Boxed -> True, Ticks -> None, Background -> Black, ImageSize -> {700, 700}, SphericalRegion -> True, Method -> {"RotationControl" -> "Globe"} ]

So the question is simple: Is there a way to get fuzzy dots/points without applying a Blur command to the whole thing, in a way that the view could still be rotated? Ideally, the solution (if any) should be applicable to an old version of Mathematica (I'm still using Mma 7.0, until I upgrade the whole computer!).

Maybe the solution is to use a sprite PNG image for each particle, but then that small picture should stay oriented front to the viewer, whatever what he do with the view. I doubt that this would work well for an output that draws several thousands of particles, and it may be way too long to program just to get fuzzy dots in a manipulate box.

EDIT:. The fuzzy sprite-like particles I would like to get are looking like this:

A single particle, without any specific color:

enter image description here

Several particles, each one using the same disk blob (or sprite), but using different colors and sizes:

enter image description here

Cham
  • 4,093
  • 21
  • 36
  • 1
    Is there any image that could help explain what you want more specifically? – rhermans Jul 28 '22 at 16:42
  • @rhermans, I simply want to add a blurry/fuzzy aspect to the particles in the manipulate box. You could check the picture I gave in my question here (which is related): https://mathematica.stackexchange.com/questions/271261/how-to-introduce-random-correlations-in-a-3d-uniform-distribution-of-points/271266#271266 – Cham Jul 28 '22 at 16:44
  • 1
    "simply" is a dangerous word. For myself, I don't understand what you want. Do you want some transparency? some texture? a non-circular shape? a hierarchy of point sizes? a different distribution (although you accepted an answer to that other question, so that doesn't seem likely)? – lericr Jul 28 '22 at 20:15
  • @lericr, I’m asking for the simplest in your list: all particles should have an identical blurry round shape. No texture! No special shape (all round disk on screen like a big dot), no variable size! The texture is made by the whole distribution. I’m just looking for fuzzy individual dots, nothing fancy. The fuzzy dots should have some transparency, yes... – Cham Jul 28 '22 at 20:52
  • I suggest you start with using Sphere instead of Point. You can easily add transparency (use the Opacity directive). Maybe Specularity would also give you something "fuzzy". For newer versions, you can also look into MaterialShading. I just played with MaterialShading on your example, and it took a long time, so that might not be a good option (and it's pretty new anyway). – lericr Jul 28 '22 at 23:29
  • @lericr, the sphere isn't an option. Rendering would be extremely slow, for many thousands of spheres (and it even crashes my old version of Mma!). So I guess that there's no simple way to get fuzzy sprite-like particles with Mathematica. This surprises me a bit, though. – Cham Jul 28 '22 at 23:44
  • Well, Wolfram Language is a general programming language. If you can define what you want, you can code it. You could, for example, map a function over your list of points that turns a single point into some other shape or set of shapes. I know you think that what you're asking for is obvious, but I (and apparently others reading this) still don't know what you actually want this to look like. If you said "I want each point to instead be a 7-pointed star with such-and-such side-lengths", then that'd be pretty easy to code up. But we're all just guessing here, so it's difficult to help. – lericr Jul 28 '22 at 23:53
  • Okay, going offline, but that update you posted made me think of RadialGradientImage. That's what I'd try next, but off the top of my head not sure how to make it work in 3D. – lericr Jul 29 '22 at 00:42
  • "the sphere isn't an option. Rendering would be extremely slow, for many thousands of spheres" -- but the requirement is that many thousands of fuzzy sprite-like particles be faster to render than spheres? In Graphics3D, not a 2D Image? – Michael E2 Jul 29 '22 at 01:21
  • 1
    @MichaelE2, yes. Fuzzy sprites should be faster than spheres. And small spheres are useless to me anyway. – Cham Jul 29 '22 at 01:37

1 Answers1

5

As OP already suggested, an image sprite based approach could be a solution, except a special rendering option "3DRenderingMethod" -> "BSPTreeOrDepthBuffer" is needed in order to give a correct result. (Note however this solution doesn't really work in 13.1, at least the Windows version, due to unsettled z-fighting.)

$Version
(* 13.0.1 for Microsoft Windows (64-bit) (January 28, 2022) *)

spriteAlpha = With[{r = 20} , GaussianMatrix[{r, r/3}] // Rescale // Chop // Image ]

sprite alpha mask

The sprites can be inserted in Graphics3D using Inset (or if multiple copies of the same sprite is needed, we could use one Inset coupled with a Translate[g, {pos1, pos2, ...}]):

graph = Module[{n = 100}
  , MapThread[
          Function[{col, pos, size, maxOpacity}
               , ConstantImage[col, ImageDimensions@spriteAlpha, ImageSize -> size] //
               SetAlphaChannel[#, maxOpacity spriteAlpha] & //
               Inset[#, pos] &
           ], {
          RandomColor[LABColor[.7, _, _], n]
          , RandomPoint[Ball[{0, 0, 0}, 1], n]
          , RandomInteger[{10, 50}, n]
          , RandomReal[{.3, 1}, n]
      }] //
 Graphics3D[#
    , PlotRange -> {{-1, 1}, {-1, 1}, {-1, 1}}
    , SphericalRegion -> True, RotationAction -> "Clip"
    , ImageSize -> 200] & //
 Style[#, RenderingOptions -> {
     (*"DepthPeelingLayers" -> 64,*)
     "3DRenderingMethod" -> "BSPTreeOrDepthBuffer"
     }] &
]

3D graphic with fuzzy sprites

It looks like this approach performs good enough on my computer. At least n = 1000 doesn't really slow down the 3D interaction. "DepthPeelingLayers" could use a larger value than the default 8 in case of really lots of sprites.

GIFs to demonstrate the 3D graphic is really transparent, also the performance on Windows:

interactive 3D graphic with fuzzy sprites demo for n=1000

Silvia
  • 27,556
  • 3
  • 84
  • 164
  • Very nice solution here, how to fix the z-fighting? With n=300 when I resize the graphic it freezes the FE... – user5601 Aug 09 '22 at 20:17
  • @user5601 Hi there, I added a GIF to demonstrate the performance on my laptop when n=1000. I suspect it varies dramatically from OS to OS. I don't have access to Mathematica with GUI on Mac or Linux, but I do know on Windows the FrontEnd uses DirectX to accelerate 3D graphic rendering, which could provide huge performance boost. – Silvia Aug 11 '22 at 07:03
  • As for the z-fighting issue, I assume you meant for 13.1? I don't know if fiddling with RenderingOptions could give result as good as the ones I saw in 13.0.1. It could be a side effect of updates of the FrontEnd in 13.1. Actually I will report that to WRI as a bug. – Silvia Aug 11 '22 at 07:08