
Show HN: 2D field of view demo - legends2k
https://jsfiddle.net/legends2k/bykd8usp/show/
======
legends2k
In case someone is interested in the design:

[https://bbcdn.githack.com/rmsundaram/tryouts/raw/e06259fffad...](https://bbcdn.githack.com/rmsundaram/tryouts/raw/e06259fffad9231172a65b66ed99406df4e051d1/CG/WebGL/FoV/design.html)

Devising the algorithm took around a month; did it in my free time. The
implementation took a week, in HTML5 Canvas/JavaScript. Doing a 360°, not-
bound-by-distance FoV would have been simpler, but FoV limited by both angle
and distance took time.

The idea is to find the field of view of an observer on a map with blocking
buildings (polygons) and also to service a line of sight query, to know if a
given point is visible to the observer.

The code contains enough comments including citations and references to
articles and books. Here's the actual repo from where the above page is
served:

[http://bitbucket.org/rmsundaram/tryouts/src/master/CG/WebGL/...](http://bitbucket.org/rmsundaram/tryouts/src/master/CG/WebGL/FoV)

~~~
feiss
Well done! It's almost the same algorithm I came up with in one sleepless
night, 7 years ago. I used it in a game that was not finished:
[http://feiss.be/games/luxi](http://feiss.be/games/luxi) (shameless Show HN)

~~~
legends2k
Wow, the visuals look stunning, I like the noir theme!

~~~
feiss
Thanks! :) It's a shame we didn't finished it..

~~~
tobinfricke
It's beautiful.

------
thomasjonas
Similar technique used for a nice website background:
[https://web.archive.org/web/20140429043206/http://www.goodga...](https://web.archive.org/web/20140429043206/http://www.goodgameclub.com/)

~~~
partisan
That looked like a very cool site and nice set of games. Time is a harsh
mistress.

------
MasterScrat
Interesting!

How much more complicated would it be if the obstacles were not polygons but
points on a grid?

I've always been curious how the FoV was computed so fast in the Baldur's Gate
games given the complex grid-based map and the weak harder at the time.

Example grid:
[http://aigamedev.com/static/tutorials/FPSB_bg_rsr.png](http://aigamedev.com/static/tutorials/FPSB_bg_rsr.png)

And the FoV rendered: [http://cdn.wegotthiscovered.com/wp-
content/uploads/Baldurs-G...](http://cdn.wegotthiscovered.com/wp-
content/uploads/Baldurs-Gate-3.jpg) (the rooms with no one in them are
slightly darker)

~~~
willvarfar
Permit me a "show HN" of my own ;)

Here's a 3D view-shed calculation on a grid.

[http://williamedwardscoder.tumblr.com/post/13269950091/a-whi...](http://williamedwardscoder.tumblr.com/post/13269950091/a-while-
ago-i-was-playing-with-computing)

~~~
legends2k
This looks great! Are the calculations done in the GPU?

~~~
willvarfar
Not the example code I pasted into the blogpost.

To be honest, its not an obvious candidate for offloading the the GPU. Its a
light task, the result is probably wanted by the CPU, and these days we
probably have spare CPU cores that could be utilized while the GPU is busy.

However, with the move towards UMA for CPUs and GPUs - even the newly-
announced ARM cores with Mali GPUs have coherent caches between CPU and GPU -
and a move towards Vulkan, then the cost will change. As the cost of getting
the result back to where its used for game logic diminishes, then this could
increasingly be a candidate for GPU crunching :)

(In my code there's a divide-per-grid-square that could be tackled using
scaling perhaps.)

~~~
legends2k
> the result is probably wanted by the CPU -- I think this is a good reason to
> do it in the CPU.

> its not an obvious candidate for offloading the the GPU -- How? Shooting a
> ray to every vertex comes to my mind.

~~~
willvarfar
> its not an obvious candidate for offloading the the GPU -- How? Shooting a
> ray to every vertex comes to my mind.

I'm not following your meaning here ;)

My blog post describes how to do it in a sweep rather than 'shooting lines',
for the performance reasons given in the blog post.

'Shooting lines' is pretty poor for performance because of data locality and
cache pressure.

In general, locality is the big performance problem with 'ray tracing' in
general. All attempts at speeding up ray tracing are about trying to make
'bundles' of adjacent rays flying in close formation that can be combined or
computed together so as to try and give some locality to the problem.

My scanline approach (line as in cache array of adjacent memory, not line as
in line-of-sight between eye and obstacle) is good for CPUs and good for GPUs.
If you want to offload viewshed computation to the GPU, you ought strive for a
scanline approach rather than 'shooting a ray to every vertex' too. My code
ought be straightforward to port to a shader.

~~~
legends2k
My bad! Of course ray tracing in the GPU would be costly; I dunno where I got
that. I think my mind is still stuck on 2D after this, need to go back to 3D
:)

When I had to do picking on a 3D terrain, I did a scanline approach too
([https://bitbucket.org/rmsundaram/tryouts/src/master/CG/Terra...](https://bitbucket.org/rmsundaram/tryouts/src/master/CG/Terrain/Picking/))

------
Grue3
The algorithm is called "recursive shadowcast" and has long been used in
roguelike games. I once implemented a vector adaptation of this algorithm for
the groundbreaking non-tile based roguelike Urban Warfare [1]

[1] [https://common-lisp.net/project/lifp/uwar.htm](https://common-
lisp.net/project/lifp/uwar.htm)

------
almightysmudge
Very nice. Did you look at [http://ncase.me/sight-and-
light/](http://ncase.me/sight-and-light/) at all?

~~~
legends2k
This too is a reference that I'd cited in the design document I'd linked :)

See the References section.

------
asQuirreL
This is some interesting work! I was musing about another algorithm to achieve
the same effect, as I was reading:

* First render the scene in 3D, from the viewer's position, using a perspective transformation with the right field-of-view to match the "bounding angle".

* Save the resulting Z-buffer into a texture.

* When rendering the 2D, top-down scene, you can consult the Z-buffer (now a texture) to see whether that pixel should be highlighted or not.

I think this is a technique that's already used, but almost complementarily,
to calculate shadows from dynamic lights.

~~~
Chilinot
Yes, it is very similar to shadow mapping.

------
manuelflara
This brings back memories of playing Commandos: Behind Enemy Lines:
[http://store.steampowered.com/app/6800/](http://store.steampowered.com/app/6800/)

~~~
legends2k
Huge fan of Commandos series and the Desperados series. In fact this was
inspired by it :) Thanks for bringing up its name!

------
mrmattyboy
I found a bit of a weird 'bug', where I could get the POV to have a straight
edge (rather than the curvature), if it's of any use:
[http://imgur.com/a/MPzGa](http://imgur.com/a/MPzGa)

~~~
legends2k
Thanks for reporting this ;)

This is a floating-point comparison problem, I faced it frequently during
development; need to play more with it to arrive at a better epsilon ε value.

~~~
Scea91
I found different bug. Might it be the same issue?
[https://imgur.com/Rxaq72M](https://imgur.com/Rxaq72M)

~~~
legends2k
This is new! I'd never hit it. But it seems the angular point sorting is off,
can you please send the browser and its build you are on? I'm unable to
reproduce it.

~~~
Scea91
Google Chrome - Version 49.0.2623.110 m (64-bit)

~~~
legends2k
Thanks, will check when I get time.

------
foota
Here's an interesting approach to do this from a game worked on by Shamus
Young,
[http://www.shamusyoung.com/twentysidedtale/?p=20777](http://www.shamusyoung.com/twentysidedtale/?p=20777)

~~~
legends2k
Seems to be a great article at first glance, will read it. Thanks!

------
sclangdon
Good job OP. I personally found Eric Lippert's 6-part series (and playable
Silverlight demo) on the subject fascinating. I didn't notice it referenced in
your design document, so here it is.

[https://blogs.msdn.microsoft.com/ericlippert/tag/shadowcasti...](https://blogs.msdn.microsoft.com/ericlippert/tag/shadowcasting/)

~~~
legends2k
Actually I've not read it, will read it some time, bookmarked :)

------
intruder
This is really cool, appreciate the demo, source and the writeup.

The debug view is beautiful. Great work.

~~~
legends2k
Thanks for your kind words.

------
xabi
Old (June 2012), but still interesting related article:
[http://www.redblobgames.com/articles/visibility/](http://www.redblobgames.com/articles/visibility/)

~~~
legends2k
This is one of the references I'd cited, see the References section in the
design document link I'd shared.

~~~
almightysmudge
Whoops, so you did.

------
damptowel
On a tangent, this reminded of this 2D shadow mapping technique.

[https://github.com/mattdesl/lwjgl-basics/wiki/2D-Pixel-
Perfe...](https://github.com/mattdesl/lwjgl-basics/wiki/2D-Pixel-Perfect-
Shadows)

~~~
legends2k
Thanks! The original inspiration cited in this (Catalin's article) did come up
during development.

------
sakri
Here's a fairly detailed blog entry about some similar explorations :
[http://barradeau.com/blog/?p=194](http://barradeau.com/blog/?p=194)

~~~
legends2k
Great link! It seems to have an in-depth treatment of the subject, thanks!

------
blastseld
I found a bug [http://imgur.com/VDQOT7o](http://imgur.com/VDQOT7o)

~~~
blastseld
[http://imgur.com/755Bnzw](http://imgur.com/755Bnzw)

------
achikin
We used to do it on coding interviews, but with rectangles only.

------
mar_tin
This looks great. Loved reading the writeup!

~~~
legends2k
Thank you!

------
Artlav
So... Can anyone explain what is so special or interesting about this?

Both the idea and the algorithms are decades old and were already used in the
80s and 90s computer games like Wolf3D and Doom.

~~~
khedoros
Even with a known algorithm, it can be cool to see a clean visualization of
it.

OP was clever enough to figure it out, and that's great, but it bugs me some
every time I see them say that they couldn't understand other people's
explanations of how it works.

~~~
legends2k
Thanks!

> it bugs me some every time I see them say that they couldn't understand
> other people's explanations of how it works.

I think I need to explain. Most of them explain their work well, but I cannot
reuse them as they all have 360° FoV, not limited by distance, while I wanted
something else, hence this mini project.

The ones which had what I wanted were closed source.

