Feb
15
2012

Raycast Visibility 2.2

This is just a updated version of the: fake realtime raycast shadows (its not really shadows though..)

Features in v2.0

  • Mesh is pre-build
  • In update loop we just modify the existing vertices (no need to triangulate, create uv’s, etc in every frame)
  • 50000 raycasts starts to get slow, but 10k is still 60fps in editor.
  • Would be interesting to add this also: Precalculated sin cos arrays
  • Some overlapping lines seem to appear (see those white lines..) not sure why, but atleast its fast : )

Ideas to try:

– Use low quality mesh in LateUpdate(?)

Bug fixes for script: “ShadowRayScan2.js”

Find line:

vertices[i] = Vector3(tmp.x,0.5,tmp.z); 

Replace with:

vertices[i] = Vector3(tmp.x,0,tmp.z);  // now the mesh wont go upwards

Find line:

vertices[i] = Vector3(tmp2.x,0.5,tmp2.z); 

Replace with:

vertices[i] = Vector3(tmp2.x,0,tmp2.z); 

*Fix for “upside down” mesh:

Find:

triangles[n] = newvertices.Length-1;

Replace with:

triangles[n+2] = newvertices.Length-1;

Find:

triangles[n+2] = i;

Replace with:

triangles[n] = i;

Find:

    triangles[triangles.length-3] = newvertices.Length-1;
triangles[triangles.length-2] = 0;
triangles[triangles.length-1] = i-1;

Replace with:

    triangles[triangles.length-1] = newvertices.Length-1;
triangles[triangles.length-2] = 0;
triangles[triangles.length-3] = i-1;

*Fix for disappearing mesh (if go further away from 0,0,0)

Find:

var tmp2 = lightmeshholder.transform.InverseTransformPoint(lightmeshholder.transform.position+dir);

Replace with:

var tmp2 = lightmeshholder.transform.InverseTransformPoint(lightmeshholder.transform.position+dir*distance);

Find (inside update loop):

mesh.vertices = vertices;

Insert line after it:

mesh.RecalculateBounds();

*More info here: http://forum.unity3d.com/threads/35897-Object-disappear-when-zooming-in-lt-URGENT!?p=628496&viewfull=1#post628496

Webplayer:
http://unitycoder.com/upload/demos/mShadowRayScan2/

Source:
mRaycastVisibility2.unityPackage

Image#2

Profiler image for ShadowRayScan4.js (512 rays)
– using SinCos lookup tables didnt make any difference
– it seems the actual raycast takes only half of the total scanning loop..?)

Image #3 : Fading light with blending shader: “Blend One OneMinusDstColor”

Shader for the fade light:


Shader "UnityCoder/LightMeshShaderGradient1"
{
SubShader
{
Tags { "RenderType"="Opaque" }
Blend One OneMinusDstColor
Lighting Off
Cull Front
CGPROGRAM
#pragma surface surf Lambert
#include "UnityCG.cginc"

struct Input
{
float2 uv_MainTex;
float4 screenPos;
};

void surf (Input IN, inout SurfaceOutput o)
{
float2 screenUV = IN.screenPos.xy / IN.screenPos.w;
float xx = 0.5-screenUV.x;
float yy = 0.5-screenUV.y;
float d = 2-(xx*xx+yy*yy)*9; // 2 & 9 are from just testing what values work on this distance..
half3 c = half3(d,d,d);
o.Albedo = c;
o.Alpha = 1; //c.r;
}
ENDCG
}
}

Image #4 : 10000 times multiplied Albedo with “Blend DstColor SrcColor” (couldnt get it any brighter..?)

Image #5: if you clone the lightmeshHolder, you get brighter light..


Image#6: Quick test using DX11 features.. so far its only 1ms faster with 20000 rays..


Related Posts

About the Author:

.fi

64 Comments + Add Comment

  • Should do a small change to it,
    instead of moving the (last) middle vertex to the player position,
    move the visibility-gameobject(where the created mesh is) to the player position.

    • This didnt work so well, the mesh is “stuttering”.. better just set the last vertex to player position, instead of moving the object..

  • Awsome, tested it in my game, you can download the webplayer, take a look and tell me what you think about it:
    http://forum.unity3d.com/threads/123143-Cone-of-Sight-Visualization?p=827826#post827826

  • I want to apply a depthMask shader for the created mesh.
    so i can use this mesh as a cutout of a viewport… but if i add the shader only the white error lines do the masking…
    why is the rest of the mesh not masking? maybe you immediately know…

    anyway THANKS so far, i helped me a lot

  • Not sure about that shader, but it looks like the created mesh is upside down.. have to try fix that.

    • lol, genius! that must be it!

  • Added couple other bug fixes on the post.
    *Adding the reversed normal fix now also, it was just a small thing.

  • added the bugfixes, 2 more questions:
    -i checked: if i watch the mesh from underneath it does the masking thing… can you show how to draw it NOT upside down? i cant simply rotate it, can i?

    not important:
    -when i the camera(specificaly the viewport reticle) moves a certain distance away from the mesh it stops rendering it (the camera can move away from the player, so moving the mesh with the player doesnt help in this case). can i set something like always render?

    Thanks for your support on this,

  • OHH, your faster than me, forget the above post, i will insert the upside down thing

    😀 many thanks

  • I made it to use the created Mesh as my cutout mask, looks awsome, now i can hide parts of the enemy, a few tweaks in my camera scripts and i can upload the next version.

    i managed the disappearance of the mesh by enabling Spherical Culling + extending cullingDistance for the MeshLayer, now i can move as far away with the splitcamera, the mesh is still drawn

    Thanks, when i finish a few tweaks i let you know what YOU made me achieve 😀

    • sounds interesting, I tried the demo earlier and it looks good 🙂

      • Ah, i was wrong, i thought ive seen it working but its not, the spherical culling + layer distance didn’t fix the not-rendering of the mesh, anyway
        Iam interested in your thoughts on THAT:
        http://forum.unity3d.com/threads/124019-SpaceNox-Working-Title?p=834143#post834143

        • added 2 fixes, one problem was, if the ray doesnt hit anything, the vertex wasnt drown in right position (the end of the ray), and then it seems to help, if you make the lightmeshholder to follow player position. (not yet sure why..)

          • Yes, it worked, but only for the ship camera, the reticule camera in game can move far away from the meshholding ship and the same problem reappears for the other side of the splitscreen
            also, as i attach the mesh to the player, the mesh gets very jumpy and shakes a bit as the ship rotates.

            -when the ray doesnt hit anything, the triangles are missing (shadow), thats why i setted the distance high and created a collision bound on the edge of the map

            there must be a “always render” flag or smth, but i didnt found it yet…

            if you are interested in messing around with it, i can send you the project, but i warn you, when you see my scripts you may facepalm so hard that the inertia of your eyeballs pulls them both out – right before your neck snaps – thrusting your head on the floor behind your seat creating an impact of one kiloton of TNT.

          • yes, I could try the files, so I can see whats happening.
            my email is here, http://unitycoder.com/blog/requests/

            also have a look at this, could be more elegant solution (although I had problems making it scan 360..but maybe 360 view is not needed)
            http://www.unity3d-france.com/unity/phpBB3/viewtopic.php?p=18274&sid=63231ea639a16863123a5a58efc08e44#p18274

  • Added 1 fix..(uh..the blog post is starting to explode, should make a new fixed package later..)

    See the link for disappearing mesh, adding “RecalculateBounds” fixes it.
    Or by making the lighmeshHolder to follow player position, inside FixedUpdate(), not inside Update() (then it doesnt shake)

    • Awsome, i thought i already tried that by uncommenting this line in your initial script
      // mesh.RecalculateBounds();
      but i didnt see that this line wasnt in the update routine :D, stupid me.

  • just putting a note to myself to test these later:
    – would soft shadows be possible with this kind of mesh plane system(?)
    – special shader (borders get transparency?)
    – vertex transparency?
    – dark “glow”?
    – duplicate plane? (scale just a bit smaller, then original plane is 50% transparent?)
    – lengthen ray, add extra vertices to the end, with vertex transparency?

  • took me some time, but i finally managed to modify your code. didnt understand anything at the time i took the first look at it.
    i tried to get better performance and now i have my solution:
    since the rays are limited, i had a jumpy visibility polygon when looking at distant edges while moving.
    But now i rotate the rays (not the mesh) with my ship AND increase the density of the rays in the forward direction, because that is the only direction in which distant looks(jumpy edges) happen anyway.
    i took a cos to increase the density in forward direction while decreasing the backward density so i get the feel of +4000 rays while using only 1024 now.

    //generate improved angles
    impAngles = new float[RaysToShoot];
    for (int i=0;i<RaysToShoot;i++){
    impAngles[i] = Mathf.PI*2 * (-Mathf.Cos( Mathf.PI*((float)i/(float)RaysToShoot) )*0.5F + 0.5F );
    }

    so thanks again for your help, now im very happy with this implementation

    • sounds interesting!
      btw. if you need to run the game on deep profiler (to see whats using the most cpu), we have pro version at the office.

      • Hey, i’ve just seen your offer to test my game in deep profiler, i will come back to that in september when i have finished my master thesis and finished the 0.9 version of my game 😀

        • Ok, msg/email me then!

          I hope 4.0 is here by then..
          Also 3.5.x has some mesh improvements, havent checked them yet, if could make it faster..

          (and there is one more “fake shadow shader” also, not published in blog yet, might be faster..?)

  • Hello mgear !

    I developing a AI enemies library. I have a some problems about FOV of enemies. I have a idea is create FOV using Raycast Visibility. I only want my enemies FOV is 60 (degree) so i were change source like this :

    In Update() (snip code)

    var angle:float = -Mathf.PI/3;
    for (var i:int=0;i<RaysToShoot;i++)
    {
    var x = Mathf.Sin(angle);
    var y = Mathf.Cos(angle);
    angle += 2*Mathf.PI/(3*RaysToShoot);
    ………
    ………

    But i have a some problem. Could you help me solve this problem ! ( That problem in red cycle of image ) Thanks so much ( sorry my bad english )
    This is image :
    http://imageshack.us/photo/my-images/84/problem1j.png/

  • Some speed increase if you remove/comment the line “vertices = ..”
    its not needed inside the Update() loop (and using now LateUpdate() in v5.0)

    function LateUpdate () 
    {
    //	vertices = mesh.vertices; // saves 3ms on my pc, when casting 20000 rays
    
  • its very posible to get visibility polygon without ray casting, 1000-10000 rays? its very slow method if it tooks 1mls than its possible to take just 0,01 mls and if there are lots of objects that needs this effect. I have code for that working fine.Demo is at my website serumas.gamedev.lt. I could share the code…

    • Looks amazing, I’ll try it soon!

      This one seems like good solution also,
      http://forum.unity3d.com/threads/142532-2D-Mesh-Based-Volumetric-Lights

      • as i saw , its based on raycast too and very very slow 20 lights and lag just with 4 walls…
        better results using computational geometry… :).
        My algorithm not perfect yet, but it tooks ~0,02-0,04 mls with 10 walls so it could be 100s of lights, it depends on wall count. And algorithm can be optimized and speeded ~2x, not finished fully yet.

        • Your demo was very smooth, does it work with moving objects also?

  • My algo has no history :), works with momential plygon positions. there is effect in action with moveing objects and explosions lights.

  • Got something similar working, no raycasts used,
    http://unitycoder.com/blog/2012/10/29/2d-raycasting-visibility-voxel-travelsal/

    But will be bit difficult to handle moving objects..

  • But its still rays. You wrote that its 512 rays in your demo. 🙂 Whats the problem with moveing objects? Chopy movement of visibility polygon?

  • That is my newiest game prototype, that uses visibility effect on each explosion dynamicaly
    http://serumas.gamedev.lt/index.php?id=combat1&sid=

  • Would this be suitable to create a field of vision for a NPC?

  • Hi mgear, I was wondering how do you achieve the effect of fading lights as shown? I am by no means a shader programmer, could you explain a little about what shader did you use?

    • Added the shader ^ (since our player is always in middle of the screen, we just fade the color based on distance from middle..)

      Other ways could be, set vertex colors or alpha for the edge vertices.

      • Thanks for the quick response! Also, another question, is there any ways to limit the raycast distance? Currently, if even one of the raycasts doesn’t hit something, the entire mesh would just show up in weird positions.

        • Ah, I seem to have found the solution by changing :

          var tmp2 = lightmeshholder.transform.InverseTransformPoint(lightmeshholder.transform.position+dir);

          to :

          var tmp2 = transform.position+dir*distance;

  • Hi, great site you got and a lot of nice stuff you done!

    Question, is it possible or easy to use this script, and make it “open-up” the world when you navigate through it. As it is now, it is a more shadow behavior and LOS function. I need a script that the user needs to explore a dark world, but once a area is discovered, I want it to be visible.

    Joakim

    • Thanks, exactly what i was searching for.

      Keep it up!

      Joakim

  • Looks interesting also,
    Visual concealment for games using Javascript
    http://www.codeproject.com/Articles/545808/Visual-concealment-for-games-using-Javascript

  • Awesome!
    Wish I could download, but it still doesn’t recognise my toolbar. I even tried stopping the page and copying the URL. Didn’t work :[
    Awesome stuff though :]

    • ^ how about now?

  • I would like to use this to “mask” the scene representing what the actor sees independently from any lights in the scene. How could I go about doing it? Is it possible to generate the inverse of the current mesh and just have a black material on it?
    (sorry for all the questions, very new to Unity and been trying to do something like this for ages!)

  • Line Of Sight / Field of View (webplayer demo)
    http://forum.unity3d.com/threads/227342-Line-Of-Sight-Field-of-View

  • Some info about raycasting performance, see “Figure 8 : Primitive vs Mesh colliders physics profiler data”
    http://unity3d.com/learn/tutorials/modules/intermediate/physics/physics-best-practices

  • this could help alot: go vote for “Enable PhysX raycast batching”
    http://feedback.unity3d.com/suggestions/enable-physx-raycast-batching

  • at 9:59, using local cubemap to generate “visibility” map where light can reach:
    Enhancing your Unity Mobile Games – Unite Europe 2015
    https://youtu.be/Z5y-PQIpSbw?t=9m59s

  • Hi there again, so how good your algorithm? Still ray cast? 🙂 jokin

  • Hi there, it seems I can’t extract the zip file. It said that the zip can’t be open by 7zip.

    • thanks for reporting! should be fixed now

      • I just successfully imported it to my project, thank you!

Leave a comment

Connect

Twitter View LinkedIn profile Youtube Youtube Join Discord Twitch

UnityLauncherPro

Get UnityLauncherPRO and work faster with Unity Projects!
*free unity hub alternative

@unitycoder_com

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.