Announcement

Collapse
No announcement yet.

Feeding material with world position offset data

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Feeding material with world position offset data

    Looking for a solution to achieve the following effect:

    Click image for larger version

Name:	disp.jpg
Views:	1
Size:	169.4 KB
ID:	1200375

    In motion:



    I’d need multiple spheres displacing a single plane mesh underneath in real time, think gravity well:
    • The size of the plane and the spheres (and their number) is dynamic and will affect the strength of the displacement
    • The distortions will overlap but will not be cumulative on the Z axis (ideally, but not really a must have)
    • The effect is purely visual, no collision, shadowcasting or additional player interaction is necessary
    • Does not need to be particularly performant
    • Does not need to be very accurate
    • I was hoping to achieve it via materials


    I’ve been experimenting with WorldPositionOffset and SphereGradient-2D and it’s easy enough to pull it off for a single instance.
    Multiple displacement effects are, of course, doable if I simply duplicate the nodes and apply unique coordinates but that’s cumbersome
    and the final number of the displacements is not fixed. And it does not feel like the right way do it anyway.

    Click image for larger version

Name:	mat.png
Views:	1
Size:	433.7 KB
ID:	1200376

    How do I send a bunch of coordinates to the material in real time? Is a dynamic texture implemented through C++ the only way forward?

    Out of the box ideas are welcome, too!
    Thanks

    #2
    to get the sphere location and radius to the material you can use https://docs.unrealengine.com/latest...erCollections/

    with this approach you will have to do the deformation for each sphere though. You could also look into using SphereMasks for the deformation so they are in 3D space.

    Another approach could be to write a displacement texture via blueprint and render it to a texture target and use that for the deformation.

    Comment


      #3
      Originally posted by divi View Post
      to get the sphere location and radius to the material you can use https://docs.unrealengine.com/latest...erCollections/

      with this approach you will have to do the deformation for each sphere though. You could also look into using SphereMasks for the deformation so they are in 3D space.
      I have no issues with location and radius, my beef is sending information from multiple actors to the same material.

      I'll be dealing with 30 actors at most. So you're suggesting a MaterialParamCollection with 30 location vectors, 30 radius scalars and 30 whichever-param-I-need and looping through the objects while setting the collection's parameters accordingly. OK, I can see it work, as awkward as it sounds.

      I used 3d sphere mask previously but run into the same issues but I can look into it again.

      Originally posted by divi View Post
      Another approach could be to write a displacement texture via blueprint and render it to a texture target and use that for the deformation.
      That sounds promising, I'll do some extra digging, thank you.

      If anyone has any other ideas, please do let me know.

      Comment


        #4
        Another idea is that you could have a scene capture actor set to Orthographic and set it to be a top down angle. Then in your spheres , you could use the vertex shader to make the spheres larger if the camera is a top down camera. You can just do a dot of cameravector with the known top down vector of 0,0,-1 to see if its true. Then you can use the depth of this expanded sphere texture on your ground to displace things.

        This is how I solve certain billboard related shadowing problems when distance fields are not an option.
        Ryan Brucks
        Principal Technical Artist, Epic Games

        Comment


          #5
          Originally posted by Everynone View Post

          That sounds promising, I'll do some extra digging, thank you.

          If anyone has any other ideas, please do let me know.
          Yeah, a bunch of separate parameters will kill your performance. It's faster to write the locations to a texture and loop through it in the material. This should get you started, it performs decently with 100 spheres:

          This material doesn't include a variable radius, but you should be able to write that to the alpha channel of your texture. You can probably find a better offset function than I used.

          Click image for larger version

Name:	GravityWellMat.jpg
Views:	1
Size:	336.5 KB
ID:	1118397

          Code:
            float3 sphereloc= Texture2DSampleLevel(Tex,TexSampler,float2(0.01+0.005,0.5),0.0).xyz;
            float3 offset=float3(0,0,0);
            float numstep=100;
          
              for(int i = 0; i < numstep; i++) {        
              sphereloc=Texture2DSampleLevel(Tex,TexSampler,float2(float(i)*0.01+0.005,0.5),0.0).xyz;
              offset+=lerp(float3(0,0,-500),float3(0,0,0),clamp(distance(sphereloc,wpos)/500,0,1));
          
              }
              return offset;
          Create a CanvasRenderTarget2D blueprint.

          Click image for larger version

Name:	GravityWellCRT.jpg
Views:	1
Size:	330.4 KB
ID:	1118396

          This actor creates a bunch of spheres above the plane, and adds their location to an array. It creates an instance of the CanvasRenderTarget2D and casts the location array to it. It creates a dynamic material instance, and uses the CRT2D as a texture parameter, and sets the material on the plane.

          Click image for larger version

Name:	GravityWellActorBeginPlay.jpg
Views:	1
Size:	399.9 KB
ID:	1118398

          Click image for larger version

Name:	GravityWellActorTick.jpg
Views:	1
Size:	344.7 KB
ID:	1118399

          Here's what it looks like:

          Click image for larger version

Name:	gravitywell.jpg
Views:	1
Size:	142.0 KB
ID:	1118400
          Last edited by xnihil0zer0; 11-15-2016, 07:28 PM.

          Comment

          Working...
          X