Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

2D Dynamic Shadows

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

  1. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    i don't know, do you want to create points behind your points (behind from your light's viewpoint)? this can be achieved by simply multiplying it (enlarging the vector)or you could set it to a fixed distance by multiplying its .normalized value. EDIT: Be aware that this only works if you are editing the vector from your light source's point of view (to get a vector pointing from your light source to your vertex: lightsource.position - vertex). you can also check my mesh generation for the inverted visibility polygon.



    Way easier is what i do in my script, i save the renderer for each polygon
    poly[iPoly].renderer = wall.GetComponent<Renderer>();

    and then i simply check if its on the screen by the flag that Unity already provides:
    if( polys[iPoly].renderer.isVisible){



    do you clear it every frame?
     
    Last edited: Feb 9, 2014
  2. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    That's probably what I'll end up doing.

    Yes I do. The reason I clear the lists every frame is so they can be updated again. This makes it dynamic, which is what I'm looking for. Down the road, I would like to have it auto detect what is dynamic and what isn't, perhaps by detecting if the object has a rigidbody. The dynamic points on the list will be cleared and updated again in case they change, the static ones will not be cleared.

    I've got a work-in-progress that is using Red Blob Game's algorithm (as well as yours) that will cast a ray to each vertex and render triangles for visibility. I don't have the triangles rendered yet, but I've got the lines casted so far. It looks like this:

    $Screen Shot 2014-02-09 at 1.21.00 PM.png

    The red lines are drawn in the direction of each visible vertex, but they end if they hit a collider before they hit their target. This collision is what makes up my endPoints list.

    I now need to do two things:
    1. Organize my endpoints by angle. In Red Blog Game's article, he does a 360 degree sweep from vertex to vertex and adds them to an array/list for triangle rendering. I will need some suggestions here.

    2. If a ray ends on a vertex, cast another ray past it. You can see in the image that some of the lines end on vertices. I need this point, but I also need the ray to continue until it collides with something that is not a vertex. How would I compare my line endpoints to my vertices to see if they're the same or not? I think this will be much easier once my lists are organized by degree.

    Making progress :) A week ago, I had trouble with drawing lines to vertices. Now I'm understanding more and more of the code you guys have already hacked away at!
     
  3. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Hmm, i am not sure, 2 ways:

    1. You could do the following, but i think this will be buggy because sometimes you'll hit the corner-vertex of the rectangle and sometimes, due to floating point rounding errors, you won't:
    Do a Physics.Linecast to the Vertex (or very close to it). If nothing is hit the vertex is visibl -> perform Physics.Raycast from that vertex in the same direction as you did the Linecast (the direction of the Linecast should be vertexPosition - lightPosition). But if another rectangle is close the raycast, it may start inside of it (again floating point errors...) so check first if the point you are starting your second raycast at isn't contained in a collider (bool Contains(Vector3 point);)

    2. OR You could ignore the raycast for the owner of the specific vertex you are casting at. But there is no way to exclude specific objects from raycast (afaik) without changing their layer (i don't know if changing layers of an object for every vertex is performance critical). This is will be much more consistent than above solution but requires saving of your wall objects to recognize the correct owner of a vertex to set its layer.
    -So make a list/array of a struct or class like i did
    --within each struct save a wall object by referencing their game object, renderer,transform and A list of its vertices.
    Then you can easily gather all vertices, check if renderers are visible and change their layer(gameobject.layer) if you currently perform a raycast to one of its vertices by iterating through this list

    Then your algorithm would look like this:
    -iterate through list of walls:
    --change layer of current wall into a layer that is ignored by your raycast's layer mask
    --raycast to all of it's vertices
    --save hitpoints (if miss save a point along the ray at some distance) in a list or array[globalWallsVerticesCount]
    --change back the layer of the object
    -AFTER all walls are finished get the angle of your collected hitpoints and sort them (arctan or pseudoangle functions)
    -then draw your mesh with this sorted list of vertices

    You only need to sort the hitpoints, not get their exact angle. This function is slightly faster than using arctan2 from what i tested, and gets you a sorting criteria:
    http://www.opengl.org/discussion_boards/showthread.php/169527-Pseudo-angles

    EDIT: Solution 2 requires your wall objects to be convex (all its interior angles are less than 180°), since you would miss raycasts on vertices that would hit the wallobject itself
     
    Last edited: Feb 10, 2014
  4. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
    That was interesting!
    Founded another version here:
    http://stackoverflow.com/questions/...y-angle-without-actually-computing-that-angle

    Now using this for calculating angles:
    Code (csharp):
    1.  
    2. float angle = copysign(1-x/(Mathf.Abs (x)+Mathf.Abs(y)),y); // get pseudoangle
    3. ..
    4. float copysign(float a,float b)
    5. {
    6.     return (a*Mathf.Sign(b));
    7. }
    Started working on that, there is webplayer demo here, planning to add Physics2D raycasts later..
    http://unitycoder.com/blog/2014/02/10/shadow-casting-2d/

    Also should test if this helps anywhere,
    http://docs.unity3d.com/Documentation/ScriptReference/Mesh.MarkDynamic.html
     
  5. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    i wanted to find something out:

    Pseudo angles are not linear in respect to the actual angle of a point, see this diagram that shows the results of the pseudoangle function i linked in ~15° steps
    View attachment 86326

    I want to find a way to use these pseudoangles to get projected points but i lack the mathematical ability to find out if this would even work, consider this small sketch and this presets:
    -i already have calculated all pseudo angles of A B C D for sorting purposes
    -i know that CD is completely behind AB
    -i know that x has the same pseudoangle as B
    -i know that interpolating between C D using their pseudoAngles and the pseudoAngle of B wont work because it is a non-linear function
    $sketch.png

    maybe there is a cheaper way of finding X than normal line-Intersection functions, given we already have above knowledge
     
  6. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    Mgear, that demo looks great. That's the kind of sorting I'm aiming to get with my vertices. Do you have any source code for it? I don't quire understand the code you've posted with copySign. Is that derived from the articles you linked to?

    And Marrt, if you're talking about finding the collision point that belongs on the same raycast as a vertex, I just do something like this:

    Raycast from lightSource.position to vertex;
    Raycast from vertex to (vertex - lightSource.position);

    I'm pretty sure you already know that, but that's what I'm doing. What I need to figure out now is whether or not the vertex is at the visible edge of a collider. If it is, store that vertex and continue the raycast past it.
     
  7. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Thanks, but i was refering to a completely geometric solution. Getting X by addition, multiplication and the like.

    News about my Build, i made progress, just wanted to share what my mistake was as i stopped implementing serumas solution half a year ago:

    Code (csharp):
    1.         for(int b1=0; b1 < line_count-1; b1++){
    2.            
    3.             SegmentLine it = segmentLines[b1];
    4.             if(it.active){
    5.                
    6.                 for(int b2=b1+1;b2<line_count;b2++){
    7.                    
    8.                     SegmentLine it_next = segmentLines[b1];//THIS! damn b1 where b2 should stand
    9. ...
    i can't believe that i took a week to not find this pathetic error before i quit on it... However, now i can dropLines while still having 700fps, a working solution is near :D

    pink lines are finally dropped in the now fixed DropLine()
    $Capture.JPG
     
  8. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
  9. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
    Yes, its from those links above, actually this should be better than the copysign thing:
    Code (csharp):
    1.     float pseudoAngle(float dx,float dy)
    2.     {
    3.         float ax = Mathf.Abs(dx);
    4.         float ay = Mathf.Abs(dy);
    5.         float p = dy/(ax+ay);
    6.         if (dx < 0) p = 2 - p;
    7.         //# elif dy < 0: p = 4 + p
    8.         return p;
    9.     }
    Just pass object or vertex position to that and it returns pseudoangle value,
    then add the values to array or list then can sort them

    (on my test those objects are around 0,0,0 point..)
     
  10. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    Thanks, Mgear!

    Your code looks sound; unfortunately, I think I may be skipping a step before I implement that code.

    Right now, I have a list of unordered vertices. I'd like them ordered as they appear in a clockwise direction around a light source. Basically a 360 degree sweep to collect vertices, similar to the process here: http://www.redblobgames.com/articles/visibility/

    I'm not sure how to compare my list items with each other and rearrange to become ordered so that my polygon draws correctly. And even after they are ordered, I don't know how I'd go about adding these to a polygon.

    Any suggestions?
     
  11. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    You can program your own quicksort or use something like this if you have a List<yourListType>:
    Code (csharp):
    1. myList.Sort((item1, item2) => (endpoint_compare(item1,item2)));
    endpoint_compare could be a self implemented function that returns 1, -1 or 0 depending on if your value is greater, lesser or equals
    ___

    Or you could implement it like this if you just have a lot of vertices in a List:
    Code (csharp):
    1. myListofVertices.Sort( (item1, item2) => ( (Mathf.Atan2(item1.y, item1.x)).CompareTo(Mathf.Atan2(item2.y, item2.x)) ) ); //untested, out of my head
    CompareTo is a standard function that compares comparable values like int and float
    ___

    If you have an Array:
    http://snipd.net/quicksort-in-c

    i never actually implemented a quicksort myself though
     
  12. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
    I just sorted them by pseudoangle, then you can connect them 1 by 1 in correct order.

    for testing i made:
    Code (csharp):
    1.  
    2. // objects array, add each vertex here (in any order)
    3. public class verts
    4. {
    5.     public float angle {get;set;}
    6.     public Vector3 pos {get;set;}
    7. }
    8.  
    9. ..
    10.  
    11. List<verts> all = new List<verts>();
    12.  
    13. // calculate pseudoangles for each verts[]
    14. ..
    15.  
    16. // sort by pseudoangle
    17. all.Sort(delegate(verts c1, verts c2) { return c1.angle.CompareTo(c2.angle); });
    18.  
    19. // draw mesh, connect triangles: center, verts[n], verts[n+1]...
     
    Last edited: Feb 20, 2014
  13. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    Great, got the endpoint vertices sorted!

    Marrt, I used your code
    Code (csharp):
    1. for (int i = 0; i < endPoints.Count; i++) {                                                                                 // For every end point in our list...
    2.             endPoints.Sort( (item1, item2) => ( (Mathf.Atan2(item1.y, item1.x)).CompareTo(Mathf.Atan2(item2.y, item2.x)) ) );       // ...compare each point and sort them to be in order
    3.         }
    where "endPoints" is the list of points that will be used as triangle vertices. I had some trouble as I didn't realize that "item1" and "item2" were establish components that I could call without defining them as variables.

    So now that I have them sorted, I'll need to do a foreach or for loop, and run through every point and use that as a triangle vert, then set the order of triangle indices. What's the best way to do this? Should I draw each triangle separately, or can I draw a polygon out of a list of ordered vertices?

    I've also got some odd flickering going on. The light triangles are sometimes rapidly thrown out of order and render oddly. Any ideas what that could be?

    I have uploaded a unity package of my progress so far in case you guys would like to have a look. There is not much in there, only a few hundred lines of code. But it's progress! I appreciate all of the input so far.

    View attachment $DynamicLightingV1.unitypackage
     
  14. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    Hey guys! It's been a few months...life got in the way.

    I still have not made any progress since my previous post. How about you?
     
  15. MaZy

    MaZy

    Joined:
    Jun 29, 2012
    Posts:
    103
    Hey guys. How can I do it for sprites? Because you use meshfilter. So I don't know continue.

    EDIT: I just used PolygoneCollider2D

    Code so far
    Code (csharp):
    1.  
    2.     public List<Vector2> vertex;
    3.  
    4.     // Use this for initialization
    5.     void Start () {
    6.  
    7.     }
    8.    
    9.     // Update is called once per frame
    10.     void Update () {
    11.  
    12.         findVertex();
    13.  
    14.         foreach(Vector2 pos in vertex) {
    15.             Debug.DrawLine(transform.position, pos, Color.white);
    16.             Debug.DrawRay(pos, pos - (Vector2)transform.position, Color.black);
    17.         }
    18.  
    19.         vertex.Clear();
    20.     }
    21.  
    22.     void findVertex() {
    23.         Collider2D [] allObjects = Physics2D.OverlapCircleAll(transform.position, 100);
    24.        
    25.         foreach(Collider2D col in allObjects) {
    26.             PolygonCollider2D poly = col.gameObject.GetComponent<PolygonCollider2D>();
    27.            
    28.             if(poly) {
    29.                 foreach(Vector2 p in poly.points) {
    30.                     vertex.Add(poly.gameObject.transform.TransformPoint(p));
    31.                    
    32.                 }
    33.             }
    34.            
    35.         }
    36.  
     
    Last edited: May 31, 2014
  16. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    Hi MaZy,

    Looks like you've got it down so far. PolygonCollider2D is an amazing component that Unity added. Now we finally have more precise edges for sprites. Awesome!

    Have you considered taking your lighting a step further with sprite height maps? You would have 2 images per each sprite you want. One being the actual image, the second being that image converted into a height map. Unity allows you to add the height map onto your sprite material, which gives your 2D image a real awesome lighting effect as if it were 3D.

    More here;
    http://robotloveskitty.tumblr.com/post/33164532086/legend-of-dungeon-dynamic-lighting-on-sprites
     
  17. MaZy

    MaZy

    Joined:
    Jun 29, 2012
    Posts:
    103
    Ok I did now like so:
    Code (CSharp):
    1.     public List<Vector2> vertexStartpoint;
    2.     public List<Vector2> vertexEndpoint;
    3.     public Material shadowMat;
    4.  
    5.     Mesh shadowMesh;
    6.  
    7.     // Use this for initialization
    8.     void Start () {
    9.  
    10.         GameObject shadow = new GameObject("Shadow");
    11.         MeshFilter meshFilter = (MeshFilter)shadow.AddComponent(typeof(MeshFilter));
    12.         MeshRenderer renderer = shadow.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    13.         renderer.material.shader = Shader.Find ("Transparent/Diffuse");
    14.         renderer.material = shadowMat;
    15.         shadowMesh = new Mesh();
    16.         meshFilter.mesh = shadowMesh;
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update () {
    21.  
    22.         findVertex();
    23.  
    24.         shadowMesh.name = "Shadow Mesh";
    25.  
    26.         List<Vector3> shadowSeen = new List<Vector3>();
    27.         Debug.Log(vertexStartpoint.Count);
    28.         for(int i = 0; i < vertexStartpoint.Count - 2; i++) {
    29.             shadowSeen.Add(new Vector3(vertexStartpoint[i].x, vertexStartpoint[i].y, transform.position.z));
    30.             shadowSeen.Add(new Vector3(vertexStartpoint[i+1].x, vertexStartpoint[i+1].y, transform.position.z));
    31.  
    32.             shadowSeen.Add(new Vector3(vertexEndpoint[i].x, vertexEndpoint[i].y, transform.position.z));
    33.             shadowSeen.Add(new Vector3(vertexEndpoint[i+1].x, vertexEndpoint[i+1].y, transform.position.z));
    34.  
    35.         }
    36.  
    37.         List<Vector2> shadowUV = new List<Vector2>();
    38.         for(int i = 0; i < vertexStartpoint.Count - 2; i++) {
    39.             shadowUV.Add(new Vector2(vertexStartpoint[i].x, vertexStartpoint[i].y));
    40.             shadowUV.Add(new Vector2(vertexStartpoint[i+1].x, vertexStartpoint[i+1].y));
    41.      
    42.             shadowUV.Add(new Vector2(vertexEndpoint[i].x, vertexEndpoint[i].y));
    43.             shadowUV.Add(new Vector2(vertexEndpoint[i+1].x, vertexEndpoint[i+1].y));
    44.         }
    45.  
    46.         shadowMesh.vertices = shadowSeen.ToArray();
    47.         shadowMesh.uv = shadowUV.ToArray();
    48.  
    49.         shadowMesh.triangles = new int[] {0, 1, 2, 2, 1, 3};
    50.         shadowMesh.RecalculateNormals();
    51.  
    52.         vertexStartpoint.Clear();
    53.         vertexEndpoint.Clear();
    54.     }
    55.  
    56.     void findVertex() {
    57.         // Get all objects with collider (for PolygonCollider2D)
    58.         Collider2D [] allObjects = Physics2D.OverlapCircleAll(transform.position, 100);
    59.  
    60.         // if found anything
    61.         if(allObjects.Length > 0) {
    62.  
    63.             // go though collider
    64.             foreach(Collider2D col in allObjects) {
    65.  
    66.                 // Get Component
    67.                 PolygonCollider2D poly = col.gameObject.GetComponent<PolygonCollider2D>();
    68.  
    69.                 // if was succesful ( or there is none)
    70.                 if(poly) {
    71.                     // get vertices
    72.                     foreach(Vector2 p in poly.points) {
    73.  
    74.                         // add to list and draw it
    75.                         Vector2 worldPointPos = poly.gameObject.transform.TransformPoint(p);
    76.  
    77.                         RaycastHit2D linecast = Physics2D.Linecast((Vector2)transform.position, worldPointPos);
    78.                         if(linecast) {
    79.                             Debug.DrawLine((Vector2)transform.position, linecast.point, Color.yellow);
    80.                         }
    81.  
    82.                         // With this ray we get a position where the shadow is allowed to go
    83.                         // we start with the point which we have detected and continue till we do not want anymore
    84.                         Vector2 direction = (worldPointPos - (Vector2)transform.position).normalized;
    85.                         Ray2D shadowRay = new Ray2D(worldPointPos, direction);
    86.                         Vector2 shadowLastpoint = shadowRay.origin + ( shadowRay.direction * 30f);
    87.  
    88.                         RaycastHit2D checkSameObject = Physics2D.Linecast(worldPointPos + shadowRay.direction*0.05f, shadowLastpoint);
    89.  
    90.                         if(checkSameObject) {
    91.                             if(checkSameObject.collider.gameObject != poly.gameObject) {
    92.                                 Debug.DrawLine(worldPointPos + shadowRay.direction*0.05f, shadowLastpoint, Color.grey);
    93.                                 // add the shadowstartpoint
    94.                                 vertexStartpoint.Add(worldPointPos);
    95.                             }
    96.                         }
    97.  
    98.                         // add the shadow endpoint
    99.                         vertexEndpoint.Add(shadowLastpoint);
    100.                     }
    101.                 }
    102.          
    103.             }
    104.         }
    105.     }

    But I never worked with these 2 guys. So I guess there I do something wrong.
    shadowMesh.vertices
    shadowMesh.uv

    I thought with an array I could do it but I get result like before.
    result:
    ss (2014-05-31 at 06.31.47).png
    Stay next to box but no shadow.

    ss (2014-05-31 at 06.32.03).png
    moving the source to bottom. Shadow moves little but box still has no shadow

    BTW: Yellow lines means there is a light and grey means there is no light (it's the shadow)
     
  18. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    MaZy,

    looks like you've done some great work so far. You're a tad bit ahead of me :)

    Do you want to cast light or shadows?

    One thing to look out for when casting light are the vertex edges. On the edge of your box, you should cast two lines very closely together. You should have one yellow line that travels right to the edge vertex, and one line extending past it to the next surface. The two lines will appear as one, but both are required to have proper light casting. This can be done by making the extending line just barely offset from the original line.

    Sorry if that sounds confusing. I am on lunch break @ my day job and don't have the time to illustrate it.
     
  19. MaZy

    MaZy

    Joined:
    Jun 29, 2012
    Posts:
    103
    I just want to cast shadows. I wanna make top down horror game.
     
  20. jn327

    jn327

    Joined:
    Nov 20, 2012
    Posts:
    6
    Hey guys. Had any luck?
    I've been trying trying something similar.
    Shadows1.png
    Think its almost there, got all the right points in a list, think the issue is either with sorting the list or generating the triangles.

    I've also tried sorting the list with:
    Code (CSharp):
    1. for (int i = 0; i < shadowPoints.Count; i++)
    2.         {
    3.             shadowPoints.Sort( (item1, item2) => ( (Mathf.Atan2(item1.y, item1.x)).CompareTo(Mathf.Atan2(item2.y, item2.x)) ) );       // ...compare each point and sort them to be in order
    4.         }
    And the result seems to end up a lot more random:
    shadows2.png
     

    Attached Files:

  21. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    jn327,

    Well you've at least got triangles being filled. That's more than I had!

    I'd recommend you check into this dev blog post here: http://ncase.me/sight-and-light/

    It's for a game called "Nothing to Hide." It was developed and the source code released for open=source
     
  22. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
    ^ that looks great.. lets convert it to unity!

    (hopefully can get started on it next week.. if someone else is also, please post here so can share code)
     
  23. jn327

    jn327

    Joined:
    Nov 20, 2012
    Posts:
    6
    Think I've found the issue with my implementation.
    So I wrote a for loop so I could see the order in which my code was drawing the vertexes. (black edges are the start and white edges are the end)
    Code (CSharp):
    1. for (int i = 0; i < lightPoints.Count; i++)
    2.         {
    3.             if (i < (lightPoints.Count -1))
    4.             {
    5.                 Debug.DrawLine(lightPoints [i] , lightPoints [i+1], new Color(i*0.02f, i*0.02f, i*0.02f));
    6.             }
    7.             else
    8.             {
    9.                 Debug.DrawLine(lightPoints [i] , lightPoints [0], new Color(i*0.02f, i*0.02f, i*0.02f));
    10.             }
    11.         }
    And the result was:
    shadow3.png

    From this I concluded that the solution would be to order it so that if the first vertex of the poly and the second one both have the same angle then the furthest one should be put first (and inverse for the next time we encounter two vertexes that share the same angle and then back to furthest first for the next,....). Otherwise if the first 2 vertexes do not have the same angle then it should be done in inverse order (closest first then furthest.... then closes furthest for the next two with same angle,.......)

    Now to try and find a way to implement that xD
     

    Attached Files:

  24. jn327

    jn327

    Joined:
    Nov 20, 2012
    Posts:
    6
    Looks like I was wrong haha.
    For some reason I thought it would follow that pattern.
    Still, It's a step in the right direction.
    I can safely say that the issue is in ordering the vertices correctly. Not just angle wise (which is working fine) but now distance wise too.

    Edit: I tried organizing them by finding vertices with the same angle and changing their order if the one behind i belonged to the same polygon as the one in front.
    Its still not perfect:
    shadow6.png
     

    Attached Files:

    Last edited: Sep 6, 2014
  25. Serge_Billault

    Serge_Billault

    Joined:
    Aug 26, 2014
    Posts:
    190
    I came across this thread today and it gave me the idea to give it a shot too. Something tell me that with UnityPro and render textures, we might pull some nice effects
     
  26. Still_Not_Good_In_Programming

    Still_Not_Good_In_Programming

    Joined:
    Sep 22, 2014
    Posts:
    1
    Looks pretty good. But how can I add this to my player in my scene?
     
  27. Nimda001_2

    Nimda001_2

    Joined:
    Sep 19, 2013
    Posts:
    63
    Hi all, I Extracted the following ideas and basically my algorithm is:

    1. Find all vertices that receive light.

    2. Cast a ray for each vertex in the same direction that the vertex.

    3. Check if the vertex is an "endpoint" (see graph)-> if so, cast another ray from the vertex to the direction that above was bringing.



    4. Generating light points.

    5. Sort points upward with pseudoangle method.

    6. Also order the points that have the same angle and place the nearest first.

    7. Use points to build the mesh.

    That's it. I use only 2 rays for each vertex.

    When make code more readable I'll share it.

    Use the most effective and less expensive methods, but equally there are many things to improve.

    2DLight
     

    Attached Files:

  28. reveriejake

    reveriejake

    Joined:
    Jul 8, 2007
    Posts:
    819
  29. Jishmael

    Jishmael

    Joined:
    Sep 1, 2013
    Posts:
    12
    Is it possible to achieve this effect with the new Unity 4.3 2D systems? (ie. 2D colliders etc.)
     
  30. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
  31. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
  32. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
  33. Nimda001_2

    Nimda001_2

    Joined:
    Sep 19, 2013
    Posts:
    63

    Attached Files:

  34. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
  35. Nimda001_2

    Nimda001_2

    Joined:
    Sep 19, 2013
    Posts:
    63
    mgear likes this.
  36. Jishmael

    Jishmael

    Joined:
    Sep 1, 2013
    Posts:
    12
    Hello there Marrt, ive been following this thread for a while now and after finally finding a 2d dynamic shadow system, i have sought after the kind of effect discussed in this post. I am unfortunately very amateur and so would much appreciate if you could walk me through how to achieve the method that you talk about in this post.
     
  37. Jishmael

    Jishmael

    Joined:
    Sep 1, 2013
    Posts:
    12
    Ive tried your system out and its great :D however, would be able to make it so that it casts shadows where the light doesnt go instead (like draw a translucent grey over the while screen and then subtract an uncoloured 'lit' area from it?)
     
  38. Nimda001_2

    Nimda001_2

    Joined:
    Sep 19, 2013
    Posts:
    63
    Good idea. have to be a alternative system with, a cast a shadow mesh based from the object that stop the light and fill with gradient material. that will give a sensation of true ilumination together with 2dlight .
    this plugin doesn't allow that, only have a " light part" :) .
     
  39. Jishmael

    Jishmael

    Joined:
    Sep 1, 2013
    Posts:
    12
    Yeah :) do you think that you would be able to implement something like that?
     
  40. Nimda001_2

    Nimda001_2

    Joined:
    Sep 19, 2013
    Posts:
    63
    Yeap, but not this week , you'll notify when i done if you want...
     
  41. Jishmael

    Jishmael

    Joined:
    Sep 1, 2013
    Posts:
    12
    Thank you and yes please :) this is why I love this community :)
     
  42. pulkit8.mahajan

    pulkit8.mahajan

    Joined:
    Aug 9, 2013
    Posts:
    1
    Hey, i have been using the above mentioned plug in for unity. The light works great, but no collisions. I'm trying to make like phases, and wanted to know how to make collisions. Thx!
     
  43. Jishmael

    Jishmael

    Joined:
    Sep 1, 2013
    Posts:
    12
    Any progress?
     
  44. Jishmael

    Jishmael

    Joined:
    Sep 1, 2013
    Posts:
    12
    Any idea how i can do this without Unity Pro? I'm still really struggling to get this effect :/
     
  45. PureArctic

    PureArctic

    Joined:
    Jun 25, 2014
    Posts:
    1
    Cloplay try using InverseTransformPoint instead and also instead of using transform.position as your origin, try using vector3.zero
     
  46. Nimda001_2

    Nimda001_2

    Joined:
    Sep 19, 2013
    Posts:
    63
    no for the moment sorry .
     
  47. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    Wow, Nimda001_2 - your asset is awesome! I got the pro version and have been using it in my most recent project. I had put a stop to all development a few months back, but this has inspired me to start again. Thank you :)

    Here are a few notes and things to think about for future implementations:

    Smarter Mesh Building
    Currently, all vertices within the light radius are stored, ordered, and then raycasted to. Once the raycast hits a collider, that point is stored and used as a vertex for a new mesh. Shouldn't we only store that raycast hit if it is either a mesh vertex or a hit point right behind an edge vertex?

    Smart-Mesh-Building.png

    Additional Collider Support - boxes, circles, etc.

    Having concave/convex support for 2d polygon colliders is really great. But sometimes, I'd like to use a simple box or circle. I know I can create these shapes roughly with the 2d polygon collider, but being able to have the 2d box collider scale & positioning functionality would be very nice.

    Circles may be tough, but instead of storing a raycast2d hit for every vertex, we could do this:
    1. Detect the angle of a circle collider in relation to the light source
    2. From the circle's center, extend outward to find the outermost circle's edges. This should be done perpendicular to the angle in step #1.
    3. Raycast from the light source to these points & gather the first hit point as vertex for the mesh
    Circle-Detection.png
    That was a bit much, hopefully that made sense!
     
  48. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    I was just thinking about my circle collider detection and thought of an even simpler way. From the light source, raycast to every tangent point on a circle collider. That should return 2 vertices which are the circle edges. Then just order them & add 'em to the mesh!

    Note - since these would be edge vertices, you'd have to continue your raycast past these to the next point like you do with polygon collider edges.

    Circle-Detection-2.png
     
  49. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,350
    ^ ive tried something similar while ago,
    http://unitycoder.com/blog/2013/01/20/fake-circular-shadow-casters/

    The idea was to take angle & distance from light/player to sphere,
    then have pre-calculated array for those shadow mesh start points at circle..(to avoid those calculations..)
    (i think it could be improved alot, maybe using those pseudoangles from this topic etc.)
     
  50. StuffMattDoes

    StuffMattDoes

    Joined:
    Aug 15, 2012
    Posts:
    29
    That's a great start! I'm no programmer, but I'll play around with it.