0
\$\begingroup\$

I´ve read several articles, tutorials about shadow casting and I think that I understand the way how it works. However I miss some of the steps. Here is included my order list:

  1. Fill framebuffer with ambient light

  2. Render light textures to the framebuffer(adding proper blending)

3. Lights have vector of shadow casters(convex polygons) and check if they touch them(by checking the distance) and if yes, I do proper math calculation to project the polygon to the right "transformation". Then I draw them as black polygons to the framebuffer

4.At the end I use this framebuffers texture and blend it with actual game textures to "do lighting (with shadows)".

As you can see I bolded the step 3 because thats where I´m lost. The first thing, how do I project the polygon? (for these polygons I have a vector of points, also a vector of edges). The second thing, is it efficient to do it this way? I mean to iterate through the possible shadow casters for each light.

Thanks for your help.

\$\endgroup\$
2
\$\begingroup\$

For your last question, yes, you have to iterate through every caster, in same cases even multiple times. I've just made a simple game based on shadow and light ( https://youtu.be/fNp7GeHxInI ). Of course it depends on your game, but I think that with 2d games it's better to draw the light, not the shadow (in this way you can blend together different lights, if you render the shadows you can't in a easy way: when you draw a shadow you can't light that area anymore now that's black (there are of course tricks to avoid this problem)). In my game I use a lot of shadow casters so, if I projected shadows a lot of them would overlapped and that's not very efficient since you're GPU has to redraw the same pixels different times. Anyway to project shadows you need the light vectors that goes to the center of your point light to each vertex of each caster, then you lengthen them till the end of your "light box" (the square which contains the light texture) or to a fixed value based on the height of the caster if the light is in an higher position. Now you have the vertices you need to draw the shadow: the polygon vertices and the end of each light vector. You draw the light and then its shadows. That's has a complexity of O(n*k) where n are the lights and k the casters.

If you wanna render lights the algorithm it's more difficult, basically you take the light center and the polygons' vertices to draw the light triangles, but you have to calculate which is the nearest wall (the one to be enlightened). That's has a complexity of O(nk²) but I think you can optimize it to something like O(nlog(k)). This way reduces the calculations done by the GPU (you only render the light pixels once and you don't even render the shadowed areas, before you render both and the shadows even multiple times), remember that the casters in a scene would be at most an hundred or similar while the pixel of a monitor are millions, so k² (the worst case) in this scenario is better than k if you will draw a lot less pixels.

For any question ask in comments. I've not been so specific because there are already a lot of tutorials online. (I can link them if you need).

\$\endgroup\$
  • \$\begingroup\$ What do you mean by drawing the light, not the shadow? According to this tutorial (fisherevans.com/blog/post/2d-lighting-and-shadows) I thought that I´m rendering the shadows as well. Btw nice video! \$\endgroup\$ – Pins Jul 23 '17 at 8:18
  • \$\begingroup\$ @Pins like this: redblobgames.com/articles/visibility \$\endgroup\$ – Liuka Jul 23 '17 at 8:23
  • \$\begingroup\$ So basically, when we talk about OpenGL, i pass a vector of shadow casters to a light, it checks its vertices if they are front face or not, then lengthen them and render the light texture as triangle fan using all vertices? (I have to also calculate the UV for the vertices used for triangle fan and also care about the order) \$\endgroup\$ – Pins Jul 23 '17 at 21:37
  • \$\begingroup\$ And also at the start I have 4 vertices, and check all vertices I will have with a center of the light. \$\endgroup\$ – Pins Jul 23 '17 at 21:47
  • 1
    \$\begingroup\$ The code it's quite a mess, basically I create a square mesh for each light and remove like with a "swiping ray" every object inside it, projecting its shadow to the border of the square. If I remember correctly It's optimized to work only with AABB casters, but I think you can easily change that (removing some assumption from the code about the aligment of the segments). It DOES NOT WORK with overlapped geometry (you can still overlap the boredrs tough). Hope I've said everything about the code, I dont remember it much :) Ask for everything. \$\endgroup\$ – Liuka Jan 14 '18 at 16:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.