User Tag List

Results 1 to 23 of 23

Thread: Material - draw a line between two coordinates?

  1. #1
    0
    Samaritan
    Join Date
    Sep 2014
    Posts
    149

    Material - draw a line between two coordinates?

    Just wondering if it is possible to do with materials, something similar to the draw debug line in blueprint, from one point to another

    Thanks

  2. #2
    0
    Samaritan
    Join Date
    Sep 2014
    Posts
    149
    I'm trying to make a scrolling minimap that can draw a line between the player and a specific location, i am able to do it in blueprint with draw debug line, but i wouldn't know how to prevent the line from going out of the minimap's frame when the specific location is out of range

    I can easily make a scrolling material but i'm not sure how i could draw a line between two coordinates

    Are there any other alternatives?

    By the way this is not a HUD, the minimap will be viewable on a LCD monitor actor, here is an example of what i'm trying to achieve

    Name:  Tracker.jpg
Views: 5172
Size:  210.0 KB

  3. #3
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Hey guys,

    Yes it is possible but not simple or cheap as Jamsh suggested. That said it was pretty quick for me to knock this out since I mess around with these type of coordinate based shapes pretty often. I did get thrown off by the missing -X after the swizzle for a bit though (DanW reminded me that y,-x is perpendicular to x,y which is how the transform here works).

    This works by drawing a line between P0 and P1. You can specify line thickness and edge hardness. It costs around 17 instructions. You could make this into a material function and use it a few times. I might do that and toss is into engine\functions.

    Name:  Draw_Line.JPG
Views: 5468
Size:  258.4 KB

    In the left preview the line goes from 0.1,0.1 to 0.9,0.9, showing that there is also end point cutoff on the line drawing.

    A simpler approach is to use a single quad mesh and use the worldpositionoffset shader to move the top 2 verts (using UV-Y coord) to the P0 location, and the bottom 2 verts to the P1 location. Then you project using the UV-X coordinate along the vector between your points for thickness.

    That is how we do alot of fake shadows for things like the hexmap in Fortnite where the objects are too small to cast nice real shadows. Then you just spawn one of these meshes, make a material instance dynamic and set the point locations.
    Last edited by RyanB; 05-06-2015 at 04:08 PM.

  4. #4
    0
    Samaritan
    Join Date
    Sep 2014
    Posts
    149
    Here's what my setup looks like, the LCD background is a simple material, the boat, player dot icon are small planes that i placed close to the screen, they get offset as the player moves around, and i can draw a debug line between them

    Name:  Tracker.jpg
Views: 5068
Size:  156.6 KB

    But if i wanted to go further in the world where point A wouldn't be in range, the line would stick out from the LCD screen, unless i could somehow mask the actors and the line in the shape of the screen

    I'm not sure what to do

  5. #5
    0
    Samaritan
    Join Date
    Sep 2014
    Posts
    149
    @RyanB, i have to give this a try, it looks very promising

    I'll see what i can come up with and will report back

    Thanks everyone

  6. #6
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Quote Originally Posted by KhenaB View Post
    But if i wanted to go further in the world where point A wouldn't be in range, the line would stick out from the LCD screen, unless i could somehow mask the actors and the line in the shape of the screen

    I'm not sure what to do
    With the material rendered line approach, the line drawing-out-of bounds issue goes away since it can only draw in the UVs of your hud material. Masking the separate actors would have to be done by creating a square shaped mask using worldposition info.

    All you really need is a way to convert your locations into the 0-1 UV space of your screen, if you haven't done so already.

  7. #7
    0
    Samaritan
    Join Date
    Sep 2014
    Posts
    149
    @RyanB, That's exactly why i'm trying to do it with materials only, the masking issue wouldn't be a problem anymore

    I already converted the locations, my player's world location offsets the heightmap background and the boat icon 1:1 with a constant 2 parameter, all that was missing was a way to replace the draw debug line between my player and the ship

  8. #8
    0
    Samaritan
    Join Date
    Sep 2014
    Posts
    149
    It works perfectly, i appreciate the time you took to help out, i couldn't have come up with this by myself, sometime i wonder how some of you guys get so good with maths

    Thanks!

  9. #9
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    I am glad it worked! Once you mess around with this sort of thing a lot it starts to get easier. Messing around in the math hall content example map can help familiarize you with the basic vector math that shows up over and over in this stuff.

    You could think of it working by first Rotating the UVs to match the angle of the line, and then its just a simple distance calculation for the line width. capping the line at the endpoints is the more Nodey part. But all that happens in the rotated Y-coordinate which makes it pretty easy.

  10. #10
    0
    Samaritan
    Join Date
    Sep 2014
    Posts
    149
    Here's the final result, it took a bit of trial and error to match all the vectors

    Venturing away from the ship

    Name:  1.jpg
Views: 4978
Size:  227.1 KB

    Venturing further away

    Name:  2.jpg
Views: 4955
Size:  244.4 KB

    Thanks again

  11. #11
    0
    haha, once again he proves the impossible possible... Ryan I haven't seen the Hexmap thing, but that sounds like you are drawing multiple (maybe 6?) lines in the material based on the same method. Is that correct?

    If so, I'm wondering if I could use it to draw a series of 2D Lines in UMG, rather than creating a custom Spline-based Widget Component perhaps.

  12. #12
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Actually for the fortnite hexmap I was talking about something different. I was talking about using vertex shaders to project a line using light vector to make fake shadows. The advantage to doing a bunch of lines that way, is that it doesnt make any master material more expensive with each new line that needs to overlap. We did this because tiny objects would not cast a very visible shadow due to how the camera is setup for the hexmap. We also used that same trick to fake the volumetric shadows of the kites at the end of the GDC kite demo since the kites were too thin to actually show a volumetric shadow.

    The basic gist of this technique is to use the mesh UVs to isolate various parts of the mesh and use vector math to push them around. I will make a quick example in a second.

  13. #13
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Ok super quick example using EditorPlane mesh.

    Material:
    Name:  WPOLine_01.JPG
Views: 5091
Size:  116.6 KB

    Result, two of "EditorPlane" mesh in the scene, on the left has the LineWPO material, on the right has default material:
    Name:  WPOLine_02.JPG
Views: 4926
Size:  19.8 KB

    So by using a global parameter for lightvector and some soft texture alphas, it is possible to make nice fake projected blob shadows from things. This has a variety of uses.

    I used the word "Projected" because with this method you essentially shrink all the verts to 0 (the 0 - worldpos node) and then "push" them in the direction of your desired line. UV-Y masks a push along the line length, UV-X masks a push along the line width vector (which is generated via cross with 0,0,1). UV-X gets biased into -1 to 1 to center it on the line. As 0-1 it would be off to one side a bit.

    It's also really easy to redo the math to go between endpoints instead. Just replace "ActorPosition" with your P0, and for "linelength" instead use the vector Length function to get length of P0-P1.
    Vector becomes P1-P0 normalized.
    Last edited by RyanB; 05-07-2015 at 06:26 PM.

  14. #14
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Heres an example from a fortnite skybox. This scene is all unlit and all the shadows are fake since the skybox would be way beyond the dynamic shadow distance.

    Each shadow under the small rocks and bushes is a single quad with a blob shadow on it, set up almost identical to the above material example:
    Name:  ShadowsProjected1.JPG
Views: 4988
Size:  50.2 KB

    The larger rock shadow is also very similar but uses a box instead of a plane and uses "worldpositionbehindtranslucency" to map the shadow which is a bit more complicated:
    Name:  ShadowsProjected.JPG
Views: 4925
Size:  89.2 KB

    Because lightvector is stored in a global parameter, all these fake shadows move with the time of day cycle.
    Last edited by RyanB; 05-07-2015 at 06:40 PM.

  15. #15
    0
    Mind = Blown.

    That's a pretty awesome technique. Since you're using it in Fortnite and the Kite demo I'm guessing it's fine, but my only concern is does it create significant overdraw with all those translucent quads over everything? I guess whatever performance you'd lose by using Dynamic Shadows you gain back in spades using this approach anyway.

    The result are pretty spectacular actually, without knowing this I'd never have seen anything out-of-place with the shadows at all.
    Last edited by TheJamsh; 05-08-2015 at 05:43 AM.

  16. #16
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Quote Originally Posted by TheJamsh View Post
    Mind = Blown.

    That's a pretty awesome technique. Since you're using it in Fortnite and the Kite demo I'm guessing it's fine, but my only concern is does it create significant overdraw with all those translucent quads over everything? I guess whatever performance you'd lose by using Dynamic Shadows you gain back in spades using this approach anyway.

    The result are pretty spectacular actually, without knowing this I'd never have seen anything out-of-place with the shadows at all.
    The little rock shadows on the ground are not bad since they are tiny and almost never overlap.

    The big rock mesa shadows on the other hand do get pretty slow since they are boxes which means you see the overdraw even where the box hits the sky.

    To mitigate that, the vertex material has a parameter to deform the box to be as small as possible from the side. Here is an example.

    With the optimization off, you can see how the projected box gets pretty huge:
    Name:  Projection_box_01.JPG
Views: 4642
Size:  97.3 KB

    With the optimization on about 50%:
    Name:  Projection_box_02.JPG
Views: 4605
Size:  80.8 KB

    On as much as it can go for this shape:
    Name:  Projection_box_03.JPG
Views: 4605
Size:  53.8 KB

    If that 'shrink' parameter was turned up any higher, you would see part of the "self shadowing" of the pillar missing either on its backside or where the ground begins to raise up a bit.

  17. #17
    0

    Thx

    Quote Originally Posted by RyanB View Post
    Hey guys,

    Yes it is possible but not simple or cheap as Jamsh suggested. That said it was pretty quick for me to knock this out since I mess around with these type of coordinate based shapes pretty often. I did get thrown off by the missing -X after the swizzle for a bit though (DanW reminded me that y,-x is perpendicular to x,y which is how the transform here works).

    This works by drawing a line between P0 and P1. You can specify line thickness and edge hardness. It costs around 17 instructions. You could make this into a material function and use it a few times. I might do that and toss is into engine\functions.

    Name:  Draw_Line.JPG
Views: 5468
Size:  258.4 KB
    Hi Ryan,

    Thanks a lot for this function.
    Not only I found it quite useful as is but it helped me a lot to do a function drawer shader.

    In my implementation I added some inputs to allow the segment to be continued as a line. You can download it here, for those who are interested.
    The function drawer is here: http://werwackfx.com/index.php/graphictools/ue4-main/ue4-articles/35-shaderwkfunctiondrawer

    Best regards

    Note: I tried to attach the file to this tread but I got this message:
    MF_WkDrawLineBetween2Coords.zip - Your file of 98.0 KB bytes exceeds the forum's limit of 97.7 KB for this filetype.
    :S Maybe the attachment size could be increased a bit, don't you think so?

  18. #18
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Thats pretty cool.

    Out of curiosity have you seen the material functions "Plot Function on Graph" and the content example level Math_Hall.umap? looks like you build something similar.
    Ryan Brucks
    Principal Technical Artist, Epic Games

  19. #19
    0
    Not sure if this is relevant (or if it has been suggested before), if so then please disregard.

    If you are looking for a method to create a dynamic line (with a wide range of visual fx capabilities and control), why not make a shader that does this to a line mesh attached to your HUD object?

    I put this together in just a few minutes. It is incredibly easy but really dynamic and utilizes the full UV point array so advanced visual effects can be easily applied (as well as motion). Even curve edits and additional points may be blended in for a relatively cheap cost.

    Name:  DynamicLine00.jpg
Views: 4509
Size:  492.1 KB

    Name:  DynamicLine01.jpg
Views: 4306
Size:  268.8 KB

    Name:  DynamicLine02.jpg
Views: 4410
Size:  293.8 KB

    Name:  DynamicLine03.jpg
Views: 4288
Size:  262.0 KB

    Name:  DynamicLine04.jpg
Views: 4272
Size:  321.5 KB

  20. #20
    0
    Quote Originally Posted by RyanB View Post
    Thats pretty cool.

    Out of curiosity have you seen the material functions "Plot Function on Graph" and the content example level Math_Hall.umap? looks like you build something similar.
    Gee!!!
    Indeed! I didn't know about that map! It's awesome, there are plenty of things there! The plot function material is incredible, the interactivity is really nice and the examples are really really cool!!

    I have many things coming to my mind when looking at all this.

    First I see there is an example for Sine (1.11). It says that the period of the implemented Sine is 1, which is quite unusual. Is there a reason for this?
    I mean, maybe it is an optimization for many things, but the time we waste, as user, to check and double check our code before discovering that!!! Is is also very disturbing because the documentation says that the implementation is in radians (cf Sine Documentation). Maybe you should fix the documentation.

    Beside at the end of the level there is the following panel about trigonometry:
    Name:  TrigoFormulae.jpg
Views: 4270
Size:  96.0 KB
    Well, strictly speaking, from a math point of view, this is not consistent with the implementation. You should mention there that the unit of X is in turns, not in radians.


    The way the functions PlotFunctionOnGraph_Setup_Input and PlotFunctionOnGraph_Derivative expose their plugs is really interesting. By using a re-entry of the value it avoids to have 2 nodes, one before the function and one after, as I did. Clever.

    The implementation I did to draw the graph is quite similar to PlotFunctionOnGraph_Setup_Input. I didn't do any correction for the thickness though. This function has some code in it for that but it looks disconnected and I have some trouble to understand if it works or if this is a rest of some code from PlotFunctionOnGraph_Derivative.
    I wasn't able to get any change on the result when I tried to change the range. It works as expected on PlotFunctionOnGraph_Derivative though. Is there something special to take the range in account?


    PlotFunctionOnGraph_Derivative is really interesting too. I think by tweaking it a bit we could make it draw parametric functions.
    In practice it is nice not to have to provide the derivative of the function to draw. Nevertheless giving 2 times the same function (x) is not always easy: inside a shader the function may be quite complex and we may not want to duplicate it, even for debug purpose. That's one of the reasons why I choose to have a pre-function and a post-function in my implementation (at the price of some lack of usability).


    It would be nice to have a true documentation page for these 2 functions, with some basic examples (after a very quick search I didn't find one for PlotFunctionOnGraph_Setup_Input).


    Ho and I forgot to say the dynamic display of the values on the graph, in the scene, is great too. I will check that in details!


    Thanks a lot for these references, they will be very helpful!


    Julien
    Last edited by werwack; 09-17-2015 at 07:38 PM.

  21. #21
    0
    Unreal Engine Developer
    Join Date
    Apr 2014
    Posts
    1,911
    Thanks for the feedback.

    Good point about the SinX thing not being literal since we change the period. In practice I use those formulas as identities though and end up using only the second part of the formula, since it can tell you which sides of a triangle you need to divide but you don't always need to perform the sine operation (unless you are doing the inverse sine which is expensive). Or for example lets say you are dealing with a dot product which by definition returns the cosine of the angle. In that case, the dot product literally is just A/H so there is no ambiguity and this can help you remember that.

    There may just be a bug with the standard PlotFunction node. I will take a look.

    And yes it is a bit annoying to plug some functions twice. At the time I didn't really understand how to leverage ddx or ddy so I could probably redo that without requiring the second input. Will have to experiment with it.
    Last edited by RyanB; 09-18-2015 at 04:36 PM.
    Ryan Brucks
    Principal Technical Artist, Epic Games

  22. #22
    0
    Promoter
    Join Date
    Dec 2014
    Posts
    184
    You guys are awesome,
    @RyanB In your post #15 the technique that you used for small rock, What you think if use this technique for a top down (Strategic) shadow ? Is it good for mobile performance ?
    And also where i can find a tutorial about that ?

    Regards
    ABC Augmented Reality by UE4
    GooglePlay

    ArchVis VR

  23. #23
    0
    Quote Originally Posted by RyanB View Post
    Ok super quick example using EditorPlane mesh.

    Material:
    Name:  WPOLine_01.JPG
Views: 5091
Size:  116.6 KB

    Result, two of "EditorPlane" mesh in the scene, on the left has the LineWPO material, on the right has default material:
    Name:  WPOLine_02.JPG
Views: 4926
Size:  19.8 KB

    So by using a global parameter for lightvector and some soft texture alphas, it is possible to make nice fake projected blob shadows from things. This has a variety of uses.

    I used the word "Projected" because with this method you essentially shrink all the verts to 0 (the 0 - worldpos node) and then "push" them in the direction of your desired line. UV-Y masks a push along the line length, UV-X masks a push along the line width vector (which is generated via cross with 0,0,1). UV-X gets biased into -1 to 1 to center it on the line. As 0-1 it would be off to one side a bit.

    It's also really easy to redo the math to go between endpoints instead. Just replace "ActorPosition" with your P0, and for "linelength" instead use the vector Length function to get length of P0-P1.
    Vector becomes P1-P0 normalized.
    This looks really good and comprehensible but how do you use it for multiple segments? Say you want to draw a parametric circle using this of say 20 segments. In a less complex engine you would just do a begin draw, call draw on the mesh with the applied material a number of times while changing the input arguments to the material and then end draw when you are done, but in UE4 i guess theres not really a traditional draw loop where you can render persistently like that so i guess every segment would need to be its own instance? Would you be able to describe how to approach this or even if you have a simple example that would really be gold worth!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •