Search Unity

Raymarching for volumetric objects

Discussion in 'Shaders' started by Cactus_on_Fire, Jun 23, 2019.

  1. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Hello.

    I made a nebula shader which basically arranges the UVs on a 10X10 texture to a 100 stacked planes and colors them. The results are pretty neat but if you try to look at it from the side, you can see the plane layers and they dissapear due to the angle.

    Is there a shader that can take the 10X10 texture and create a 3d object that uses raymarching to display it as a volumetric object?



     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,339
    Certainly you could do raymarching. Usually you want to convert your atlas into a Texture3D to make things a little easier, but it’s not required.

    Alternatively you could use something like your existing mesh, but rotate it in the shader to face the camera and have it sample that 3D texture in the object’s original orientation.
     
  3. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    There's little to no documentation I could find on creating Texture3D's from image sequences rather than procedural shaders. There is another asset that displays texture3D in a volumetric way but it doesn't say how he created the Texture3D from image slices.
    Do you know a way to create Texture3D from images?
     
  4. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    328
    There is a code for generating volume texture (replace "hash" function by own code) :

    Code (CSharp):
    1.     void GenerateVolume (int size)
    2.     {
    3.         Texture3D volume = new Texture3D (size, size, size, TextureFormat.ARGB32, true);
    4.         var voxels = new Color[size*size*size];
    5.         int i = 0;
    6.         Color color = Color.black;
    7.         for (int z = 0; z < size; ++z)
    8.         {
    9.             for (int y = 0; y < size; ++y)
    10.             {
    11.                 for (int x = 0; x < size; ++x, ++i)
    12.                 {
    13.                     color.r = hash(new Vector3(x,y,z)).x;
    14.                     color.g = hash(new Vector3(x,y,z)).y;
    15.                     color.b = hash(new Vector3(x,y,z)).z;
    16.                     voxels[i] = color;
    17.                 }
    18.             }
    19.         }
    20.         volume.SetPixels (voxels);
    21.         volume.Apply ();
    22.         material.SetTexture("volume",volume);
    23.     }
    Example shader to render texture3D:

    https://forum.unity.com/threads/how...ccess-them-from-a-shader.607780/#post-4089262
     
  5. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    As I understand, it encodes the texture to the rgb channels as coordinates. Which unfortunately doesn't allow color or alpha channel.
     
  6. zenden_1

    zenden_1

    Joined:
    May 20, 2017
    Posts:
    53
    Hey, i'm curious about what you do. Can you share your code if it is'nt private please ?
     
  7. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    It's not really a code it's just a bunch of stacked planes that use the nebula atlas maps to create a volumetric 3d nebula.









     
    RedEarth, killer1171090 and protopop like this.
  8. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Im a bit late but if possible you could try getting more of these Atlas images for every side you could be facing so 6 different atlas maps (Thats if your using 1 sided planes, if its 2 sided you could use 3 instead) Then get the Dot value of the Cameras position relative to a planes direction, and slowly fade the plane the more of an angle your looking at it from. So when your looking from the side, all planes that would normally show its edges would be completely invisible. This would be the Easier option, and possibly on the faster side of things. You wouldnt need 100 layers on each axis, could probably get away with more like 50 maybe even 20.

    Another option which you already mentioned is converting it to a 3d texture, which in theory shouldn't be to hard todo.
    But the best approach may be to simply use that atlas directly inside a shader.
    And add a converter for 3d positions to a 2d position.

    So something like this:
    X, Y positions are left untouched, they grab the 2d position in the texture inside one of the cells.
    but the Z axis instead of simply trying to grab something from a 3d texture, just offset the X, Y positions according to the Z value.

    So lets say each image inside your atlas is 32x32 and the full image is 64x64.
    You are trying to get the position at 0, 0, 0
    In this case you first find the offset with the Z value, so the First image in the atlas, so dont offset the X, Y positions. and simply grab the color there.
    Now lets say you want to get 1, 1, 0. Same thing, your trying to get a value at depth 0 so you dont need to offset the X, Y positions.
    Ok what about 0, 0, 2? Well in this case you want to grab the 3rd image in the atlas in this case we need to offset the X, Y positions to match where texture we want is now.

    If done right it should be fairly performant not much of a different between an actual 3D texture and this.

    Hopefully i understood your question correctly and this helps you out!
    Though i am curious, how did you come to obtain these? were they procedural generated or crafted by hand? They look amazing!
     
  9. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Thanks. I made an after effects animation with turbulent noise where it creates a nebula shape when layered like this. In Unity I use 100 layers minimum and 250 maximum, anything lower than that creates those stepping artifacts.

    I had problems converting and using the textures with the 3DTexture technique but the best way I found for this was to make the 100 layer planes face the camera at all times and place the textures in worldspace so no matter what angle you look at it from it looks volumetric.
     
    killer1171090 likes this.
  10. wzgzebragoogl

    wzgzebragoogl

    Joined:
    Jun 1, 2020
    Posts:
    3
    Excuse me, how do you solve the results are pretty near but if you try to look at it from the side, you can see the plane layers and they demonstrate due to the angle.My results are as follows
     

    Attached Files:

    • 3d.png
      3d.png
      File size:
      150.6 KB
      Views:
      397
  11. wzgzebragoogl

    wzgzebragoogl

    Joined:
    Jun 1, 2020
    Posts:
    3
    thanks a lot
     

    Attached Files:

  12. wzgzebragoogl

    wzgzebragoogl

    Joined:
    Jun 1, 2020
    Posts:
    3
    I've solved the problem. Thank you
     
  13. InfinityGameDev

    InfinityGameDev

    Joined:
    Jun 28, 2016
    Posts:
    54
    Hey @Cactus_on_Fire , did you create these atlas maps or did you get them from somewhere? I'm interested in testing something similar out
     
  14. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    I made them with after effects. In the noise settings you can select something like spline dynamic and increase the evolution over time to make this.
     
    InfinityGameDev likes this.
  15. Buttermilch

    Buttermilch

    Joined:
    Nov 23, 2016
    Posts:
    33
    I've actually made a free simple tool for that since I found little to no resources for this.
     
  16. InfinityGameDev

    InfinityGameDev

    Joined:
    Jun 28, 2016
    Posts:
    54
    Thanks y'all!
     
    Cactus_on_Fire likes this.