Search Unity

  1. Engage, network and learn at Unite Austin 2017, Oct 3 - 5. Get your ticket today!
    Dismiss Notice
  2. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  3. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  4. Unity 2017.1 is now released.
    Dismiss Notice
  5. Unity 2017.2 beta is now available for download.
    Dismiss Notice

2D Dynamic Shadows

Discussion in 'Scripting' started by Clopay, Jan 7, 2013.

  1. Clopay

    Clopay

    Joined:
    Aug 15, 2012
    Posts:
    29
    Hey all!

    So I'm on a mission to incorporate dynamic shadows into a 2D game (think Thomas Was Alone style). I know such a feat is possible in Unity Free because that's where Thomas Was Alone was developed.

    Anyways, I got a hold of some code generously provided for us here by ivkoni a few years back. Although this code is nifty and gives the visual I'd like to achieve, it doesn't necessarily function the same way. The provided code requires you to attach the shadow rendering script to every object in the scene that you want to have a shadow, along with establishing empty game objects on each of these objects from which the shadow would be drawn. My idea would be a tad different.

    I've provided a basic graphic of the following mockup:

    I'd like to have all of the code and operations be handled in a single gameobject (such as a light point). This light point will consist of a light point origin and a "shadow texture" in the form of a plane that will extend to the camera boundaries. This texture will NOT be immediately visible. The texture will be placed in the same Z depth as every other object in the scene, and will thereby detect all such colliders. It will extract the vertices of each object, from which some fancy math will be used to calculate a polygon from the outermost vertices of the objects extending to the edge of the screen. Finally, within this polygon the shadow texture will be visible.

    From what I understand based on watching Mike Bithell's videos/blog posts, this is similar to how TWA calculates its shadows - no raycasting involved.

    How far fetched would this be for us to accomplish here for everyone else yearning for similar results?

    Thanks in advance!
    -Clopay
     

    Attached Files:

  2. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
  3. MikeBithell

    MikeBithell

    Joined:
    Jan 8, 2013
    Posts:
    2
    Hey, yep.. that's precisely how I did it, warping 2D planes as you describe.. only difference is that I didn't think to crop based on screen space.. because I'm an idiot :D

    Only limitation of this solution is it really only works in a straightforward fashion for rectangles. Obviously fine in my case, but potentially problematic for anything more advanced.
     
  4. MikeBithell

    MikeBithell

    Joined:
    Jan 8, 2013
    Posts:
    2
    ah.. one difference.. I actually used planes rather than rendering / unrendering textures... so each shadow is a 2 poly mesh squished about a bit
     
  5. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    @Mike, your game looks really nice and polished :D

    i really hope i can improve my shader knowledge to the point of understanding this approach and modify it to my needs.
    http://www.catalinzima.com/2010/07/my-technique-for-the-shader-based-dynamic-2d-shadows/
    the raycasts are just way to expensive for my needed resolution (~1000 rays) and above solution's shadowtexture doesn't grow with zoom level but with screen resolution giving you pixelaccuracy on any zoomLevel at a constant computation load.

    we will see how far i get as i have finished the core of my game and start to learn shaders. But im not a game developer, i am just doing it for myself, i am not looking forward to make money out of anything :)
     
  6. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    3,958
  7. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
  8. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    -ok, tonight i started to code on this thing for Unity, maybe we can figure it out together if you guys still want this,
    i will try desperately at least...
    -i just started with the mesh member variables so i am pretty sure i do nonsense yet, but its a start.

    my progress:

    1. PREPERATION i filter out all vertices that have their normals pointing down (.normals.y=-1), we are now 2D
      [*]PREPERATION then i create a Vector3[][] in the meaning of Vector3[polygon#][vertex#]
      -currently the order is wrong if i dont exchange the last with the first vertex, i have to study meshes some more
      [*]FACES: then i calculate which edge would be visible (ignoring occlusion), just checking if the source is on the right half of the edge

      FUTURE, see serumas solution:
      [*]SEGMENTS (whatever he does there. do you know?)
      [*]LINES
      [*]CUTS
      [*]RECALC
      [*]FINAL


    lets hope for the best... :confused:

    Download removed: outdated, check newer posts
    $Capture.PNG
     
    Last edited: Jan 16, 2013
  9. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    3,958
    Looks good so far, I'll test it also.
     
  10. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    I contacted sarumas, he offered me his c++ code, now i am awaiting his email :D

    Until i get it i will update the testscene and script a bit to have the 2D polygon extraction ready, i think my current polygon extraction will lead me nowhere... however, what i have now is:

    a struct[] for the polygons
    -to store additional stuff for each polygon (like relevant-radius or attached ScriptComponents to fade the wall out)

    all vertices and triangles of the bottomplane
    -but i cant get the outlining polygons points in the right order for every possible polygon

    so basically i need to solve:
    "Is there a way to get outer points in right order ccw or cc of any convex or concave polygon?(inverse triangulation?)"
    found something useful maybe, im reading it... Link
    Edit:got it! : "A boundary edge is an edge that belongs to exactly one triangle" with that i can create the polygon now... cant wait to get home

    my current package, the old Vector3[][] can still be found but is not used anymore, i will remove it at the next update:
    View attachment $GeometricVisibility-v0.1.unitypackage

    info:
    why do i even make everything dependent on the bottomplane?
    -since these 2D fake shadows are to be used in top-down or sidescroll 2D environments we could always flatten and use the invisible bottom side of objects as sight-blocking-polygon reference
    -note: maybe of use for flattening the bottom Fracture
     
    Last edited: Jan 16, 2013
  11. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    I think my Polygon extraction is working now:

    View attachment $GeometricVisibility-V0.13.unitypackage

    what am i doing in there?

    GeneratePolygonStructArr()
    • checking Size of valid Vertices for array initiation(i know, List would be better)
    • save all valid Vertices and their indices from the original mesh
    • extract all triangles using these points and set their indices corresponding to the new bottom vertices[]
    now i basically have a new plane-mesh that is the bottom plane of the object. now i call ExtractPolygon passing these arrays


    ExtractPolygon()
    • get all edges of the triangles
    • extract all boundaryEdges (edges only present in exactly 1 triangle)
    • sort edges List in a way that adjacent edges are next to each other
    • easily extract the vertices out of this sorted list
    • ccw-check, check if the inner angles in ccw direction are less than the outer angles
    • -this is needed if the poly was extracted in the wrong direction (depends on original mesh vertices order)
    at last save the list as vertices[] in the Polygon struct, its now ready for use :D


    EDIT v0.13:
    -added random Polygon generator
    -added some buttons
    -added FixCCWOrder (now always detecting the correct faces)
    -fixed a small error in the sort loop of boundaryEdges

    $Untitled.png

    -i am currently adding serumas algorithm to this package
     
    Last edited: Jan 20, 2013
  12. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    I am still working on the conversion of serumas c++ code, i'm slow (inexperienced with c++ syntax, can't use std::vector)

    Does anyone know if my substitude for std::vector is good/bad:
    -Serumas uses "std::vector <SEGMENT>" where SEGMENT is a struct. He passes this struct by Pointers most of the time (to avoid copy overhead i think)
    -In C# i imitated this by using a List<SEGMENT> but SEGMENT as a class (because it is passed by reference, since pointers to structs are considered unsafe i've read somewhere)
     
  13. wbokunic

    wbokunic

    Joined:
    Dec 17, 2009
    Posts:
    43
    Going to bump this thread because I have something to add. I was able to modify the way shown here to cast shadows like what Clopay wants. It's still using Raycasts, so it's slow, but it's better than nothing for now.

    The way I did it requires Unity Pro, but essentially I have a separate camera capture the additive output from this script over a black background. I output that to a texture file using RenderTexture and put it onto a plane in-front of the Main Camera. I then set the material to Multiply. In essence this flips the what the script does and only darkens the environment where you can't see. Here's a few screenshots of it in action:

    $dmdXWlT.png
    This was immediately after I got the effect to work. I hadn't yet made it look good in the environment.

    $0nZX6KN.png
    After some tweaking it looks quite nice.
     
  14. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Very nice,

    i dont have unity pro but i was able to overlap viewports to get your shine through effect with a depth mask shader.
    it is bad since it overwrites rendered parts of a viewport = processing power lost for invisible rendering.
    if you want to check it i just uploaded my whole build:
    http://forum.unity3d.com/threads/12...-Title/page3?p=1186317&viewfull=1#post1186317


    i feel ashame that it takes me so long to convert c++ code for the geometric visibility... but i am still on it, its just that i suddenly had very few time for programming it ~1hour/week
     
  15. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    3,958
  16. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    I just bought this asset to check its internals out
    https://www.assetstore.unity3d.com/#/content/3787

    i found that on bottom it just uses raycasts again. There are some neat selective Update features however.
    ____________________


    In the meantime i sporadically work on the geometric visibility based on serumas solution, i e.g scripted a kind of occlusion diagram to help me debugging/understanding his occlusion checks:

    $occlusion diagram0.jpg

    $occlusion diagram.jpg

    so the topic is not dead for me, in fact its the only thing i do when i have time for unity
     
    Last edited: May 4, 2013
  17. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    3,958
  18. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    I found some time again, so it's only a matter of time until i finally have it :D. currently it looks like this:

    $Untitled.jpg

    obviously i have some errors caused by my conversion of this code:
    http://www.redblobgames.com/articles/visibility/

    The unoptimized performance currently is about 150 fps while processing 500 segments with ~4 points average on them

    My current algorithm is a kind of patchwork of different algorithms:
    -first i extract all polygons of my wall objects with my extraction (only once at Start() )
    -then i create segments out of them with a very modified version of serumas code
    -then i use serumas check functions to identify and drop invisible segments
    -remaining segments are converted to lineSegments (each lineSegments contains only 2 points)
    -these lineSegments are fed into a c# version of the redblobgames algorithm i have not perfectly converted yet
     
    Last edited: Jul 18, 2013
  19. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Ok, something is working now, with a few errors in special cases, check the Webplayer:

    http://marrt.elementfx.com/GeometricVisibility.html

    - most debugging features won't show since they heavily rely upon Debug.Drawline which is missing in the WebPlayer build (i just discovered GL.LINES and consider them).
    - I could post the whole project if someone wants to have a look at it now, but it is unbelievable messy.
    - maybe their is potential to use threading for this algorithm in future, since its a big seperate junk with no Gameobject interaction within its gears
     
    Last edited: Jul 18, 2013
  20. castor

    castor

    Joined:
    Sep 9, 2012
    Posts:
    30
    I've implemented your previous version on my project and it works very well.
    If this version is more optimized I would love to have a go at it!
     
  21. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    i am interested, would you show it someway?

    Don't be too faithful, i started this thing 6 months ago :D
    Right now it may be the ugliest code mash-up on earth, i need some days to eliminate bugs and write it in a decent manner but the mesh generation etc. is already working. If i would post it now you wouldn't even know where to input your vertices . But when it is finished the easiest usage case will work like this:

    >Attach the script to any GO
    >choose a GO as center of visibility
    >Tag your wall objects "Wall" for static objects
    >make sure that your walls have a flat bottom face facing in -y direction or adjust the if(....normals.y=-1) to your needs

    >choose between
    >visibilityPolygon
    >inverted visibilityPolygon (surrounding rect or circle with the visibility polgon cut out of it)
    >extrusion of the polygon (making it a prism for usage in 2.5D environment)​


    Remarks:
    - scripts are c#
    - only walls that are visible in a viewport (Renderer.isVisible) are used in the calculation to improve performance
    - optionally you can manually choose which walls are included in the calculation by supplying a rectangle of the area (i need this because i use a splitscreen setup that may have to include objects between the 2 cameras that aren't visible)
    - mutliple visibilityPolygons are no problem - if you have the performance
    - it cannot meaningful support mutliple inverted visibilityPolygons for obvious reasons (the invisible areas would add up instead of the visible)
    - it is manufactured for top-down environments (all points on X-Z-plane) if you want it for a side scroller (e.g. X-Y-Plane) you only have to insert the z-values as y values before calculation and read the output.y as z-value

    - if i continue to succeed with this it will be completely free​
     
    Last edited: Jul 18, 2013
  22. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
  23. johnetc

    johnetc

    Joined:
    Oct 15, 2012
    Posts:
    3
    This is great, Marrt. I'm trying to come up with my own version, so I understand each individual process, but your code has been extremely helpful.

    I'd been struggling with raycasting for ages.
     
  24. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    The new version won't involve raycasting at all, i hope i can fix the errors soon so i can finally post something useful
     
  25. neiledwards

    neiledwards

    Joined:
    Aug 9, 2012
    Posts:
    2
    Marrt, I would also love it, if you would post your most recent version of your geometric visibility sources. That is if you are interested in sharing. I am currently working on a top-down, heavily stealth based games, and could really use a project to use as a base for the visual effects necessary for the game play experience I am trying to create. Regardless your work looks great, and resources thus far have been helpful exploring this concept.
     
  26. neiledwards

    neiledwards

    Joined:
    Aug 9, 2012
    Posts:
    2
    I would also greatly appreciate any resources (scripts) you would be willing and able to post. I'm working on a top-down stealth based game and your work is excellent, and it would be great to use as a starting point for the mechanic I'm trying to implement

    -Thanks for all the info and help so far
     
  27. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Hi, i'll post it when i fixed the errors, there are some sorting problems coming from my bad conversion from haxe into c#:
    $Capture.JPG



    In the meantime you can take a look at that:

    http://www.redblobgames.com/articles/visibility/
    that is the current implementation i am using, from what i have tested it is not as fast as serumas solution but it is easier to understand
     
  28. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Finally something to post.

    i reconverted the geometric sweep one more time from a different view and now it is working,
    i also added a option to insert a round boundary for a light like effect...

    source:
    View attachment $GeometricVisibility v0.6.7z

    webplayer in my signature is also up to date

    next step for me:
    - handle intersections
    - change angle sorting from Mathf.Atan2 to slope mentioned by redboxgames for performance
    - investigate why errors happen when i remove the outer border from the segment list
     
  29. luispedrofonseca

    luispedrofonseca

    Joined:
    Aug 29, 2012
    Posts:
    599
    This is incredible!!! And it seems a lot more performant than all the other solutions I've seen around.
    I am VERY interested in this and would love to see it in the asset store. I'm sure this would be a sales champ.
     
  30. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    I won't sell it as an asset, it will be free for anyone to use and improve. I make enough money in my every-day-job so i really don't need to squeeze out money of this hobby.

    additionally i believe if more people have a look at it, errors and optimizations will be easier to spot - yielding an overall better solution than i would have ever been able to come up with. I will soon make an Work-In-Progress thread for this Geometric Visibility and occasionally improve it. What's obviously missing is intersection handling, but i am on it.

    -If you want to dig deeper:
    you can have a look at the OLD scripts included in this package, it is a failed try to convert serumas code. It has even more performance mainly due to an additional pre-drop phase of whole segment-trains and the usage of pseudo angles instead of ATAN2 but i failed at the segmentLine dropping phase. I could easily merge them together (i did for testing purpose) but it was very messy to read and understand.
     
  31. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    1,920
    This thread inspired me to try this effect, without checking any of the sources, I mean, I read over some of the informative links people posted, but I wanted to see how I'd do it blind.

    [​IMG]

    https://dl.dropboxusercontent.com/u/157182894/Builds/test/Light/Light.html

    Works without any raycasts, infact there arent even any colliders in the scene.
    Doesnt work when lines cross, or with open-ended chains of lines.
    Day was fun
     
    Last edited: Aug 3, 2014
  32. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    nice that people do within one day where i tinker weeks on... but i have started programming feb 2012

    I don't use Colliders either, i extract a kind of bottom polygon out of mesh data. that means the segment-chain that is blocking the lineOfSight is essentially the outline of the bottomplane of that wall-objects.

    looks promising, i will check your build as soon as is come home since dropbox is blocked at my working place for security reasons...
    How is the performance? webplayers are frameratelimited so you won't really see how much it could push through.

    intersections should not be the problem, the thing is that i don't want to do a whole additional pass of all segments - only checking for intersections. I want to directly modify them in the segment_inFrontOf check because it also checks for intersections. Then i only have to modify the two intersecting segments without the need for an additional check.
    That should increase the performance compared to a whole pass of all segments only to check intersections
     
  33. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    3,958
    Thanks for the source!

    Made some different tests here,
    using screenshots in indie to get dynamic collision map/grid..

    Can "cast shadows" from any objects visible to the camera (particles too),
    also can adjust the height from which the scanning is done (in the webplayer: tree trunk casts shadow at ~0.5 height, but not the whole tree)
    http://unitycoder.com/upload/demos/VoxelTravelsalShadow2/

    *based on this: http://dev.mothteeth.com/2011/11/2d-ray-casting-on-a-grid-in-as3/
    (no physics raycasts used)
     
  34. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    1,920
    Alright I had a look through the provided source, and incorporated some of the smart optimisations, my performance for large numbers of sides shot up (10 fps at 450 sides (with the old [moved here]) up to 10 fps at 4200 sides [~9000 sides with closed polygons, open sides are less performant becasue they cannot be so easily discarded])
    [​IMG]
    I also moved my calcs into a coroutine, so the speed of the main game loop isnt adversely affected for reasonable numbers of sides -
    and with only a slight decrease in mesh updating, barely noticeable when the source moves very fast.
    The new code also allows open polygons (hold shift when rightclick), but is still confused by overlapping

    Shaping up, but can still be pushed further!
    https://dl.dropboxusercontent.com/u/157182894/Builds/test/Light/Light.html
     
    Last edited: Aug 3, 2014
  35. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Nice!

    Care to share your optimizations? I am not very experienced with optimizations so i think there are a lot of things in my source that could be done way better... e.g.
    -is the usage of "ref" in my functions good for speed? i thought its faster since it doesn't copy structs
    -should i use a class instead of struct since they are passed by reference right away?

    Performance Thoughts...
    i still believe serumas solution performs best, he does some neat predrops:
    predrop1: take only the polys you need (polys in range of the light)
    predrop2: do an overlap check of whole segments (trains of lines) with their angular bounding box (startangle, endangle, mindistance, maxdistance)

    rest is pretty much what i have now except for the intersections.

    The most important predrop concerning usage in actual game-maps will be the cheap "withInRectangleStrip"-check predrop i am doing next. Then you can specify a rotateable rectangle to only include intersecting polygons into the calculation of a certain light.
    meaning:
    -if your lightsource is outside of the viewport, you only need to get the polys that are on the viewport + the ones that are between it and the light
    -if your lightsource is within the viewport, only taking polys within the viewport into the calculation is enough


    i always end up making tl;dr posts :-?
     
  36. Andrew-Chewie

    Andrew-Chewie

    Joined:
    Aug 28, 2012
    Posts:
    9
    How's going optimization of the script? Is there some news? Demos? =)
     
  37. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Last edited: Sep 17, 2013
  38. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    1,920
    Wisdom

    Just checked mine, seems I didn't update my latest progress, and over-wrote the webplayer to something else (woops)
    It appears that I 'solved' my overlapping issue by dividing new lines into shorter segments, so overlaps 'work' now.
    I also tried messing with vert colors, and added the option for circular boundaries.

    But then
    Gotta pay those bills
     
  39. Clopay

    Clopay

    Joined:
    Aug 15, 2012
    Posts:
    29
    Hey guys,

    I thought I'd commented on this day or two ago, but I guess not.

    I just wanted to stop by and say awesome work! I was lead back to this thread after wanting to figure this out again, and I am amazed at some of the things you guys have managed to produce. I am looking forward to seeing where it goes!

    Unfortunately, as coding is not my strong point, I haven't gotten anything running. In fact, I'm still struggling to create an array of triangle edges. Any suggestions?
     
  40. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Hi Clopay,

    I was working on my build yesterday, added some kind of intersection handling, but it has bad performance, i just split the lines on the intersection point rather than cropping it...

    I am not sure what you want (mesh triangles?), but maybe this helps:

    in my code there are various spots where i initialize mesh data. The vertices and the triangles are the most important for my purpose and they work like this
    Code (csharp):
    1.  
    2. Vector3[]   vertices    = new Vector3   [vertCount];
    3. int[]       triangles   = new int       [vertCount*3];
    4.  
    vertices are the vertices of your mesh of course, the triangle int[] defines the triangles of you mesh and contains the reference indices to the vertice array.
    Say you have the 4 points of a rectangle and you want 2 triangles to connect them. Than you need an triangles-int-array with 6 values in it: {0,1,3,1,2,3}. Be aware that the order matters, if you type {0,3,1} rather than {0,1,3} the triangle visible face is on the other side.

    http://docs.unity3d.com/Documentation/ScriptReference/Mesh.html
     
  41. Clopay

    Clopay

    Joined:
    Aug 15, 2012
    Posts:
    29
    Marrt,

    I am just trying to mimic the code in your most recent build. I am using the same exact logic, but I am re-writing it myself for the sole purpose of understanding how it works.

    I suppose I don't really need triangles at all, but rather the vertices of the mesh. When I get the vertices of the triangle, I end up with 6 as expected. But when getting the vertices of the mesh, I end up with 4, so I assume the shared vertices are left out. I'm not sure if I'll need to keep the shared vertices just yet.

    Here's what my vertex finding process looks like right now:
    Code (csharp):
    1.     public MeshFilter[] allMeshes;
    2.     public Vector3[] vertices
    3.  
    4.     void Start () {
    5.         allMeshes = FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[];
    6.     }
    7.    
    8.     void Update () {
    9.         for (int i = 0; i < allMeshes.Length; i++) {
    10.             vertices = allMeshes[i].mesh.vertices;
    11.         }
    12.     }
    But the problem is that for every mesh filter I have, the 4 vertices get replaced with new vertices, instead of adding to the array.

    In your code, it looks like you've got a struct of the polygons. I've never used structs, but tell me if I'm right: you create an array of structs, with each struct representing a different polygon in the scene. The polygon structs contain information about the polys, and also store an array of vertices (which are ordered CCW). From this organized information, you can create edges, determine if the edges are facing you, and so on. Basically, you have an array of polys which each have an array of their vertices. How close am I?

    I know I'm a bit behind on this logic, but like I said - my programming knowledge is not expansive. For what I seek to create, this dynamic shadows part is the toughest obstacle in the entire code. I think the next step for me is to do some research on how to properly use structs.

    And I really appreciate all your input. You've done some seriously amazing work from me just simply posing a challenge on here. Hopefully I'm able to contribute!
     
  42. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    Everthing you wrote is correct. Have you discovered this link in my code: http://www.redblobgames.com/articles/visibility/

    this is were i got the "#region THE ACTUAL ALGORITHM" part of my code and this is the main thing that one should try to understand, and i don't even completely get it...
    I just advice you NOT to learn from my code, i tinkered around with functions by replacing some small things like Vector2 with Vector3 and the whole thing is still a mess and no one knows why i use X Y there and X Z within other functions or why i use referentiall coordinates here and absolute there...

    To get started just create some 2 point segments, feed them to THE ACTUAL ALGORITHM i got from Redblobgames (using addSegment) and begin to visualize everthing with Debug.Drawline instead of messing around with meshes.
     
  43. Clopay

    Clopay

    Joined:
    Aug 15, 2012
    Posts:
    29
    I did see your link. I actually reached out to the guy who wrote it, and he's been informing me a little about his code method. He is a really brilliant guy. I copied his javascript from the browser, and am reading through it. The difference is that he renders the light, while we're rendering the shadows. But what if we did try and render the light?

    Also, since Unity 4.3 has come out since I started this thread, we can now work in a 2D environment. Would that greatly simplify things?

    And I have been doing my best to tinker with all the existing code you have and everything else on this forum. The only problem, like I said, is my ability to program. I have pretty firm logic through and through for the system I'd like, but I just can't seem to get even 50 lines into it without not knowing how to program it. Something tells me that it is much simpler than how I've been trying to do it.


    Also, for my code posted on my previous reply - it's correct to an extent. I run into a problem with filling out the vertex array. The array would only include 4 vertices, when I want it to include every vertex of every mesh. But for that, I'd need another dimension, being the mesh it belongs to. So I was thinking of using a Vector3[poly][vertices] but I don't know how to create/write to those and couldn't quite decipher it from your code! Was there any reason you dropped the Vector3[ ][ ] method used in your earlier builds?
     
  44. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    i have written mesh generation code for both, you can either put a visibility polygon on the visible area (the white one) or a kind of inverted polygon (black one) onto the invisible area (Press the "Inverted" button), be aware that the outer ring of this inverted polgon should not be within a viewport because it is ugly

    I don't know, for geometric purposes not, everything i do is already 2D (working with x and y cordinates), but maybe the new 2D classes have some form of superoptimized 2d raycasts, then you should reconsider mgear's solution again :D

    yes, i needed more information for each polygon, now they have values for their position, estimated radius, active flag... all to check if we can exclude them from the occlusion checks (save performance)
     
  45. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    3,958
  46. Clopay

    Clopay

    Joined:
    Aug 15, 2012
    Posts:
    29
    I just purchased 2D Volumetric Lights on the Unity asset store, $15 to do what we're looking to do.

    http://u3d.as/content/reverie-interactive/2d-volumetric-lights/36x

    I've attached a screenshot here. It's ALMOST perfect...You can render light or shadows with it, and it has a couple of circular adjustment handles that adjust both the light radius and the angle of light. It runs in edit mode, which is really nice. All that is required is that you drag and drop a script onto an empty game object in the scene. It's almost perfect!

    $Screen Shot 2014-02-04 at 10.12.07 PM.png

    ...except it uses raycasting. Dang! If only we could implement this system but with the squished meshes as we've been doing.

    On a positive note, I have successfully drawn a series of rays from one point to a series of vertices, and even past them. I have 4 rays being drawn from the source to the vertices, and another set of rays being drawn from the vertices to a certain distance. It's primitive in comparison to what we've seen here, but it's progress for me! Now I need to find the end points of the rays, and draw meshes with them. Then do that for every mesh in the scene within our radius. Any suggestions?

    $Rays.png
     
  47. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    check out this post http://forum.unity3d.com/threads/165283-2D-Dynamic-Shadows?p=1236742&viewfull=1#post1236742
    -I mentioned that this thing uses raycasts, so you have worse performance if you have many objects, big light radii or many rays for accuracy (but does this matter to you)

    For your question above, do you want to crop the lines?
    if you really want the geometric approach you need to calculate where the colored lines are intersecting (and if) with the mesh edges.

    Also:
    your sample pic looks like a platformer, normally a platformer happens on the XY-plane, i started to built my build for a top-down shooter so i use the XZ-plane. This is nothing restricting but currently i have no clean writeup of my code where it immediately works if you just switch z with y on input/output functions. However, because i also need this for a platformer expect an easy switch between planes when i finished my code (somewhere in the year 2067 :D )
    You could just rotate everything to the XZ-plane and change the gravity vector if you dont want to look through 2500 lines of my crappy code
     
  48. Clopay

    Clopay

    Joined:
    Aug 15, 2012
    Posts:
    29
    Here's a problem I keep running into. I am trying to draw lines from a light source to every vertex within view, and I am ending up with Vector3 points as local points and not world points. Here's my code:

    Code (csharp):
    1. public class DynamicShadows : MonoBehaviour {
    2.  
    3.     // Inspector variables
    4.     public MeshFilter[] allMeshes;                              // array for all of the meshes in our scene
    5.     public List<Vector3> allVertices = new List<Vector3>();     // list for vertices
    6.        
    7.     // Called at beginning of script execution
    8.     void Start () {
    9.  
    10.         // Step 1: obtain all active meshes in the scene
    11.         allMeshes = FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[];
    12.  
    13.         // Step 2: Obtain vertices for each mesh
    14.         foreach (MeshFilter mf in allMeshes) {
    15.  
    16.             Vector3[] verts = mf.mesh.vertices;         // ====== This is where the vertices need to be added in world coordinates instead of local ======
    17.  
    18.             for (int i = 0; i < verts.Length; i++) {
    19.                 allVertices.Add(verts[i]);
    20.             }
    21.         }
    22.     }
    23.    
    24.     // Update is called once per frame
    25.     void Update () {
    26.         foreach (Vector3 vertex in allVertices) {
    27.             Debug.DrawLine(transform.position, vertex, Color.red);
    28.         }
    29.         for (int i = 0; i < allMeshes.Length; i++) {
    30.             Debug.DrawLine(transform.position, allMeshes[i].transform.position, Color.white);
    31.         }
    32.     }
    33. }
    What I have done is created a list to store all vertices in the scene. I collect every object in the scene that has an active mesh filter and store that into an array. For each mesh filter, I obtain the 4 vertices. I add these 4 vertices to my vertex list on every iteration of my for each loop.

    My problem is that using TransformPoint() does not work, nor does InverseTransformPoint.

    Any ideas?
     
  49. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    456
    You are right, you need to transform the vertex into world coordinates, i do the same thing in my code:

    My code:
    Code (csharp):
    1. bottomVertices[iv] = wall.transform.TransformPoint(vertices[i]);
    That could work for you, you need to transform every point seperately in respect to its transform. replace your foreach loop:
    Code (csharp):
    1. foreach (MeshFilter mf in allMeshes) {
    2.     //Vector3[] verts = mf.mesh.vertices;   //scrap this
    3.     for (int i = 0; i < mf.mesh.vertices.Length; i++) {//do everything right away
    4.         //transform vertex[i] of current mesh into world coordinates and add it to the list
    5.         allVertices.Add( mf.transform.TransformPoint( mf.mesh.vertices[i] ) );
    6.     }
    7. }
     
    Last edited: Feb 8, 2014
  50. Clopay

    Clopay

    Joined:
    Aug 15, 2012
    Posts:
    29
    Great! That works, thank you Marrt.

    Now I am trying to do 2 things here. The first is similar to the red blob games article we talked about. Now that I have a list of vertices, I am trying to draw triangles from the light source to each pair of vertices. It would be drawn like this:

    newVertex1 = light source.position;
    newVertex2 = vertex[0].position;
    newVertex3 = vertex[1].position;

    drawn triangle from these points;

    newVertex1 = light source.position;
    newVertex2 = vertex[1].position;
    newVertex3 = vertex[2].position;

    drawn triangle from these points;

    This would repeat for every pair of vertices we have, simulating the area where the light hits (I am going to move onto shadows after this).

    My code is here:
    Code (csharp):
    1. void Start () {
    2.  
    3.         // Step 1: obtain all active meshes in the scene
    4.         allMeshes = FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[];
    5.  
    6.         // Step 2: Obtain vertices for each mesh
    7.         foreach (MeshFilter mf in allMeshes) {                                                  // Foe every active mesh filter that we have...
    8.  
    9.             for (int i = 0; i < mf.mesh.vertices.Length; i++) {                                 // ...and for ever vertex we have of each mesh filter...
    10.                 allVertices.Add( mf.transform.TransformPoint( mf.mesh.vertices[i]));            // transform each vertex[i] of current mesh into world coordinates and add it to the list
    11.             }
    12.         }
    13.  
    14.         // Create the shadow game object
    15.         GameObject shadow = new GameObject("Shadow");
    16.         shadow.transform.position = transform.position;
    17.         MeshFilter meshFilter = (MeshFilter)shadow.AddComponent(typeof(MeshFilter));
    18.         MeshRenderer renderer = shadow.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    19.         renderer.material.shader = Shader.Find ("Transparent/Diffuse");
    20.         renderer.material = shadowMaterial;
    21.  
    22.         // Create the mesh for the shadow game object
    23.         Mesh shadowMesh = new Mesh();
    24.         shadowMesh.name = "Shadow Mesh";
    25.         shadowMesh.vertices = new Vector3[] {
    26.             new Vector3(transform.position.x, transform.position.y, transform.position.z),      // Vertex 01
    27.             new Vector3(allVertices[0].x, allVertices[0].y, transform.position.z),              // Vertex 02
    28.             new Vector3(allVertices[1].x, allVertices[1].y, transform.position.z),              // Vertex 03
    29.         };
    30.         shadowMesh.uv = new Vector2[] {
    31.             new Vector2 (transform.position.x, transform.position.y),
    32.             new Vector2(allVertices[0].x, allVertices[0].y),
    33.             new Vector2 (allVertices[1].x, allVertices[1].y)
    34.         };
    35.         shadowMesh.triangles = new int[] {0, 1, 2};
    36.         shadowMesh.RecalculateNormals();
    37.         meshFilter.mesh = shadowMesh;
    38.     }
    It does draw a triangle, but not at the right points. I believe I need to implement TransformPoint() somewhere, but I'm not sure where.

    The 2nd thing I am trying to do is make it dynamic. Here's what I think we could do:
    1. Use Physics2D.OverlapCircle() to determine what colliders are within the light source's radius - this is so that we don't bog down our CPU by getting every single vertex in the scene every frame.
    2. If the collider's within our light radius have a mesh, add them to our meshes array.
    3. For every mesh in our array, obtain their vertices and add them to our vertex list. This will refresh every frame, making it dynamic.

    The problem I run into here is that when I use List.Clear(); it does not work. So the list keeps getting added to every frame, which severely decreases framerate.