9

I'm working on a relatively small 2D (top-view) game demo, using OpenGL for my graphics. It's going for a basic stealth-based angle, and as such with all my enemies I'm drawing a sight arc so the player knows where they are looking.

One of my problems so far is that when I draw this sight arc (as a filled polygon) it naturally shows through any walls on the screen since there's nothing stopping it:

http://tinyurl.com/43y4o5z

I'm curious how I might best be able to prevent something like this. I do already have code in place that will let me detect line-intersections with walls and so on (for the enemy sight detection), and I could theoretically use this to detect such a case and draw the polygon accordingly, but this would likely be quite fiddly and/or inefficient, so I figure if there's any built-in OpenGL systems that can do this for me it would probably do it much better.

I've tried looking for questions on topics like clipping/occlusion but I'm not even sure if these are exactly what I should be looking for; my OpenGL skills are limited. It seems that anything using, say, glClipPlanes or glScissor wouldn't be suited to this due to the large amount of individual walls and so on.

Lastly, this is just a demo I'm making in my spare time, so graphics aren't exactly my main worry. If there's a (reasonably) painless way to do this then I'd hope someone can point me in the right direction; if there's no simple way then I can just leave the problem for now or find other workarounds.

Linkage
  • 307
  • 2
  • 6
  • I'm actually looking for something similar, to handle shadows in a top-down tile game. My suspicions thus far have been along the lines of raycasting (slow but perfect) and creating a mask from the occluders and some sort of shadow-mapping esque mechanic. – ssube Sep 23 '11 at 01:15
  • Have you considered just using OpenGL lighting? It might mean a bit of work, but a light positioned appropriately might give the wanted effect. – Keith Sep 23 '11 at 01:22
  • @Keith: Thanks, that might be a good idea. My experience with lighting is also limited, and I would probably need to make a number of adjustments to my draw code to make it all work. But I'll keep that in mind if nothing better comes up. – Linkage Sep 23 '11 at 01:25
  • 2
    "OpenGL lighting" doesn't handle shadows. So it would go through walls too. You would have to use shadowmapping or stencil shadows or something. – Nicol Bolas Sep 23 '11 at 01:35
  • The tricky part, as far as I can tell, is turning the 2D level into something that can be used to cast shadows onto the map (well). Plus, I have yet to figure out what the hit is on that. – ssube Sep 23 '11 at 02:27

3 Answers3

4

OpenGL's built-in occlusion handling is designed for 3D tasks and I can't think of a simple way to rig it to achieve the effect you are after. If it were me, the way I would solve this is to use a fragment shader program, but be forewarned that this definitely does not fall under "a (reasonably) painless way to do this". Briefly, you first render a binary "occlusion map" which is black where there are walls and white otherwise. Then you render the "viewing arc" like you are currently doing with a fragment program that is designed to search from the viewer towards the target location, searching for an occluder (black pixel). If it finds an occluder, then it renders that pixel of the "viewing arc" as 100% transparent. Overall though, while this is a "correct" solution I would definitely say that this is a complex feature and you seem okay without implementing it.

Matt Fisher
  • 213
  • 1
  • 9
  • 1
    That's going to be *expensive*, but it could work. Drawing them as transparent might be slower than using the built-in discard, though. – ssube Sep 23 '11 at 02:36
  • Quite a cool idea and one that will work down to pixel-level features. There'll be a fair amount of load on the GPU, but if the sight-arcs cover a relatively small portion of the screen it should be fine. – geofftnz Sep 23 '11 at 03:24
4

This is essentially a shadowing problem. Here's how I'd go about it:

For each point around the edge of your arc, trace a (2D) ray from the enemy towards the point, looking for intersections with the green boxes. If the green boxes are always going to be axis-aligned, the math will be a lot easier (look for Ray-AABB intersection). Rendering the intersection points as a triangle fan will give you your arc.

As you mention that you already have the line-wall intersection code going, then as long as that will tell you the distance from the enemy to the wall, then you'll be able to use it for the sight arc. Don't automatically assume it'll be too slow - we're not running on 486s any more. You can always reduce the number of points around the edge of your arc to speed things up.

geofftnz
  • 9,954
  • 2
  • 42
  • 50
  • This sounds fairly good, though I'd still be a bit concerned about the speed. I mean, suppose I have up to 10 enemies in one map, say at least 30 arc-points per enemy, and say 25 walls... that's 10 * 30 * 25 intersection-checks for one frame, which sounds like a lot of processor work for a relatively simple effect. Regardless, it's a good answer, and I might give it a try soon. – Linkage Sep 23 '11 at 04:24
  • 2
    Don't forget about [spatial indexing](http://en.wikipedia.org/wiki/Spatial_database#Spatial_Index) to reduce the number of walls you have to check for intersections. – genpfault Sep 23 '11 at 05:48
4

I figure if there's any built-in OpenGL systems that can do this for me it would probably do it much better.

OpenGL is a drawing API, not a geometry processing library.

Actually your intersection test method is the right way to do it. However to speed it up you should use a spatial subdivision structure. In your case you have something that's cries for a Binary Space Partitioning tree. BSP trees have the nice property, that the complexity for finding intersections of a line with walls is in average about O(log n) and worst case is O(n log n), or in other words, BSP tress are very efficient. See the BSP FAQ for details http://www.opengl.org//resources/code/samples/bspfaq/index.html

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Never looked into BSP trees myself before, but looking over it now seems very useful indeed. I'll probably try implement it if I end up working with geofftnz's earlier suggestion (or if I find my collision systems lacking later on). – Linkage Sep 23 '11 at 12:05