Hi!
I’m beginner with a three.js, so sorry in advance for my, maybe, stupid question.
I have a scene with couple of 3d models on it, which can cast and recieve shadows. In other words I have couple models of buildings, solar panels and moving “sun” as a DirectionalLight.
The question is:
Is it possoble and, if it is, then how to measure area covered by shadow on model?
For example I have a building model and it cast shadows on a solar panel, each period “sun” is moving so shadows are moving too and I need to know how many area on the solar panel is shadowed.

I’m beginner with a three.js, so sorry in advance for my, maybe, stupid question.

First, that question isn’t stupid at all - second, it also sounds like exactly the opposite of stupid - and a fun problem to solve.

But, unfortunately, I don’t think there’s any super easy solution for that - personally I wouldn’t use visuals, since they depend on the screen resolution, shadow resolution, fov, and a bunch of other error-prone and expensive moving parts.

Raycasting and partitioning sounds like an effective approach though (esp. since you’ll have to approximate minimum detectable area anyways - and with rays you can just subdivide the surface to adjust the level of approximation.)

2 Likes

Thank you very much for your solution!
But I thought maybe there is a way to achieve this somehow on stage for shadow calculation? Why I’m saying this, because I have 64^2 objects (ideal it may be 128^2) and ray casting may cause a lot of calculations.

Well, it definitely could be possible - but assuming a user has a 4K resolution screen, to determine coverage using rendered scene you’d have to iterate through 8.294.400 every frame

While it’s possible to optimise the rays using different algorithms and assumptions (they are really just a bunch of vectors in an array) - I don’t think you could easily optimise the need to of interpretation of every pixel of the screen (and every pixel could potentially be a solar panel when there’s 128² panels in the scene.)

a fun problem to solve

I second that, a fun visibility problem indeed! And three.js allows you to test out different approaches, iterate, and evaluate decisions quick, so it is a perfect match for me.

@mjurczyk strategy seems fairly efficient on its own, I would definitely try this with your assets and build a real prototype to really put it to the test.

On a side note, looking at this codepen just reminded me that you should include sun orientation with respect to panel surface normal, on top of occlussion from nearby buildings, as this angle is kind of relevant for energy performance (the closer to the normal the better).

Alternative approaches to consider for occluded panel area/percentage estimation:

• If you narrow the shadowmap size until it fits panel proportions, you could count black pixels in a dedicated shader and simply multiply by pixel resolution (aka ground sample distance, or the actual size each shadowmap pixel measures in real world). I have taken this route in the past to leverage gpu calculation when number.of objects simply forbids using CPU. FBOs are independient from scene complexity, and gives you control of a couple of things also to fine tune optimizations (i.e. render to a.downsampled version of the screen size, different values per pixel, color depth, temporal-based accumulation, etc).

• a totally different approach could be performing a shadowMesh using panel geometry as the projection receiver, and then calculating area from resulting mesh vertices. This clearly will not scale well with 128^2 individual objects, but maybe helps you think of out of the box before jumping to build a specific demo

1 Like