3
\$\begingroup\$

I've a 3D-game using perspective view, through raycasting, I create a mesh that represents the line of sight of my characters.

I'm looking for a way to "darken" (think old-school Fog of War - Unexplored = pitch black, explored but not in sight = darkened) the entire area outside of this mesh, preferably using a shader?

Black grid above scene doesn't really work well with perspective camera + mesh, as they create the hole based on the camera and not the unit. (i.e, I want the shader to act upon the characters line of sight and not the characters line of sight as seen by the camera - otherwise units can see behind walls).

Anyone have any pointers on how to achieve this?

In the following image, the white area is a mesh created by raycasting, I'd like to create a fog-of-war shader that darkens everything outside the LoS-mesh in screen-space.

enter image description here

The result should be similar to what you'd see in older roguelikes, I think it's called "shadowcasting", but in 3D.

enter image description here

\$\endgroup\$
4
  • \$\begingroup\$ youtube.com/… . Also, if you want to create a fog of war then you need to change a texture every time fog of war changes. A common solution to this is drawing a very small texture, then scale it, then smooth it, then apply it to view. You can also use a ready solution, here you go github.com/LeLocTai/Fog-of-war . But your question isn't quite in the rules of the community. I have found all the tutorials and materials on this topic myself, this means you can do it too! \$\endgroup\$ Commented Oct 11, 2017 at 16:09
  • \$\begingroup\$ And it's like one of 20 questions about the fog of war in this community + this question doesn't add anything new. gamedev.stackexchange.com/questions/75957/… gamedev.stackexchange.com/questions/87456/… gamedev.stackexchange.com/questions/134040/… \$\endgroup\$ Commented Oct 11, 2017 at 16:13
  • \$\begingroup\$ @Candid Moon Those tutorials use a radius when drawing the fog of war, ie, for x radius, draw a lightened circle around this point. I am looking for tutorials where the shader creates the fog of war from my 2D (flat) mesh. The stencil shader only works in ortographic/topdown view - I'm looking for tutorials/resources/anything regarding similar shaders that works in 3D-perspective, I am currently editing my post and will add some pictures to create a better description. \$\endgroup\$
    – ag4w
    Commented Oct 11, 2017 at 16:27
  • \$\begingroup\$ @DMGregory I apologize for being vague in my original post, I've edited the post and added pictures to clarify what I'm looking to accomplish. \$\endgroup\$
    – ag4w
    Commented Oct 11, 2017 at 16:41

2 Answers 2

1
\$\begingroup\$

Well, it appears to me that you already have part of the solution.

You should accumulate the raycast mesh over time, that gives you a 'memory' of what you've seen. Then you need to render your scene using two different lighting solutions ...

1) The Visible view - what your player character can see now. Use normal lighting such as HSAmbient + Point + Cone

2) The Seen (Memory) view - what your player character has seen. Use a darker lighting solution - eg hemispherical ambient lighting only.

Anything else is not rendered (black).

So looking at your image. You have the Visible mesh but you are making the mistake of rendering Not-Yet-Seen environment with the Visible lighting solution, specific to your image you have a global point/spot light lighting up unexplored environment - You should only render with environmental lighting when that environment is in LOS. So first render Has-Seen environment with ambient lighting solution (including the current visible mesh), then for the environment that intersects with your Visible mesh, render that with full lighting solution (excluding the already computed ambient term). You can then composite the two outputs.

enter image description here

\$\endgroup\$
3
  • \$\begingroup\$ Sorry for a slightly slow response, this causes multiple issues. Most notorious being that the mesh is 2D, it's not feasible to do volumetric raycasting due to performance reasons, and if I render the 2D mesh to the camera as some form of mask - I get artifacts along walls and similar where the player doesn't see "above" the mesh even though they should. This is solvable by raycast upwards from the mesh outline, but it's not very elegant and not really feasible in terms of performance either. I was really hoping this would be solveable via a screenspace shader instead. \$\endgroup\$
    – ag4w
    Commented Oct 12, 2017 at 16:44
  • \$\begingroup\$ Some other ideas I've had are .. 1) Use the alpha layer (if you're not using it) or keep an extra texture for all surfaces, each texture / layer is a map of what part of the surface you've seen already. You can then check this texture in shader to know if you've seen the pixel before. 2) If you constrain the view to be orthogonal (at an angle - so isometric) then you'll have a 2d view of the world, and you can paint the visible scene onto a mega texture to record the level that you've seen. \$\endgroup\$ Commented Oct 18, 2017 at 9:35
  • \$\begingroup\$ This is really just half an answer. A good answer would not just talk about the theory but deliver a working solution. \$\endgroup\$
    – Philipp
    Commented Feb 13, 2018 at 13:01
0
\$\begingroup\$

What you need to do is to do a point light based shadow casting with the light being the character. Ie:

  1. Take a depth based cubemap at the position of the character (without the character rendering in it), each frame.

  2. Bake world position and visibility (that start all black) in a lightmap style texture, each pixel test to see if it's behind the depth of the shadow map.

    a. if visible write a grey color to the visibility channel, output a white color to teh screen

    b. if invisible they do nothing (if previously visible it will be grey else it's black)

\$\endgroup\$

You must log in to answer this question.

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