5
\$\begingroup\$

I would like to create a forest scene where directional light moves through the trees canopy and is projected onto the terrain and characters underneath like so:

forest canopy floor lighting

I'm using Unity 5.6. My tree line is not in view of my camera which is set to isometric. I thought because there is no need for the tree models, I would create a quad between my directional light source and terrain. The quad would have a material with a perlin noise texture and cutout transparent shader. A majority of my scene is under the canopy with sporadic light leaking through:

My question, is the a performant way to reproduce the effect or is all the shadow casting expensive? Is there a better way to produce the effect so that my dynamic gameobjects receive real-time lighting? Is there a texture or noise function that better represents a forest canopy?

\$\endgroup\$
0

2 Answers 2

7
\$\begingroup\$

This sounds like a job for Light Cookies.

These have a number of advantages over the shadow mapping method you describe:

  • Cookies can represent intermediate levels of brightness, helping you get those soft bokeh edges and dim partial transparency that can be difficult to achieve with shadow maps.

  • The cookie can be tiled and scaled independent of your light's shadow maps, helping you keep fine detail in the dappling without increasing your shadowing workload.

Here's a quick mock-up I made, rendering a particle system into a RenderTexture using a separate camera/layer, and applying that texture to my directional light as a cookie.

Animated light dappling with a light cookie.

With a more sophisticated setup you could ensure the cookie tiles seamlessly over large areas, or layer-together sprites representing clusters of leaves that jiggle around to give a more consistent/structured look rather than the random blobs I've used here.

You could of course render your cookie with a noise-based material and blit it to the texture using pure math to form the shapes, but you might find layering objects in front of a camera makes it easier to fine-tune the look you want, or achieve things like controllable wind.

\$\endgroup\$
3
  • \$\begingroup\$ +1 for a lightweight approach. This looks really awesome. Is it possible to get a higher-resolution image? It's really hard to see the animation. \$\endgroup\$
    – ashes999
    Jul 1, 2017 at 21:39
  • \$\begingroup\$ There's not really more detail to see in a higher-res image. This was just a quick proof-of-concept, so it's really blobby. ;) \$\endgroup\$
    – DMGregory
    Jul 1, 2017 at 21:45
  • \$\begingroup\$ This is fantastic ! Thanks again @DMGregory, you continue to teach young grasshopper! It appears the cookie method is similar to my thought process, but probably has a very optimized rendering pipeline under the covers \$\endgroup\$
    – user101118
    Jul 4, 2017 at 5:28
0
\$\begingroup\$

is all the shadow casting expensive?

That all depends on how much detail you're willing to drop. How accurate do you want this to be?

Fully accurate = casting through all individual branches and twigs = fine grained 3D volume grid or CPU-intensive geometric approach = costly. Self occlusion = potentially costly. Desired ground-dappling resolution will also affect the number of rays to cast per unit area, affecting cost.

Some possible solutions...

  1. Treat the canopy as though it were flat, and store as a bit map (2D boolean array with each entry being shadowed/occluded or lit/unoccluded). Start the raycast at the level of this canopy bitmap, and cast the few meters / units to the ground. Unless occluded by trunks, rays will always reach the ground, and the distance to cast each ray will be fairly short.
  2. Use a quadtree instead of a fixed-resolution 2D array / bitmap. This will allow you to only do many raycasts in areas around each tree's canopy; in open glades, the quadtree will use a coarser resolution, reducing the number of rays. This is conceptually similar to the concept of orthogonal ray packets, where several rays are treated as a single ray in certain special circumstances.
  3. Enforce a maximum tree / canopy height to ensure the number of ray steps stays reasonable.
  4. Reduce the number of "dapples" per square meter, as much as you can while still allowing for a fair visual impact. You can adapt this into a LoD approach that depends on how far camera is.

Ultimately, you either do this using pure geometric approaches, or you break your space down into a regular 3D grid (voxels), even if that is only for purposes of calculating lighting. They both have their pros and cons. Voxels do make this process a little easier for those not very mathematically inclined.

Your other questions

We don't encourage multiple questions in one (and these are indeed totally separate problems), but briefly, you don't mention what sort of lighting you're using: forward vs. deferred, screen space vs world space, so it is really impossible to answer that. As for the most accurate pattern production - if I were you, I'd analyse my trees' volumes into an octree, then simply flatten the z aspect of the octree in order to get your flat canopy bitmap from which you can then raycast the forest floor.

P.S. Raycasting a canopy space accurately is a task challenging enough for the best procedural programmers using native languages and GPGPU tech; Unity is no match for these sorts of problems.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think you may be thinking of a much more heavyweight solution than OP has asked for. The question talks about using a single quad with a noise-based alpha tested cutout material, casting shadows through Unity's built-in shadow mapping pipeline. While raycasting/marching through a multi-layered canopy simulation is certainly one possible approach, it seems like overkill for something we can approximate to the level of fidelity that OP has described much more cheaply, with no explicit raycasting at all. \$\endgroup\$
    – DMGregory
    Jul 1, 2017 at 15:03
  • \$\begingroup\$ Thank you @Arcane Engineer, I was looking to emulate the lighting without actually adding geometry to my scene (though I have culling enabled). You are correct I did not describe my render pipeline, i am using deferred rendering. As mentioned by previous comments, I was looking more towards just masking my light and unity light cookies seems to be designed for this task. I will gauge the performance in my scene prior to leveraging further optimizations! Cheers \$\endgroup\$
    – user101118
    Jul 4, 2017 at 5:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .