Search Unity

[CONFIRMED NOT DIRECTLY SOLVABLE]How to get exit vertex position in given ray direction (ShaderLab)

Discussion in 'Shaders' started by highFlylowFlow, Dec 28, 2020.

  1. highFlylowFlow

    highFlylowFlow

    Joined:
    Nov 27, 2019
    Posts:
    15
    I want to make a shader that uses entire volume of mesh, regardless of its shape to display a volumetric effect.
    I already made few test raymarching shaders that work, no problem there, but they all rely on vertex position of the first visible vertex ("entry" vertex) and they use math primitive to determine the needed volume. I'd like to consider entire volume of arbitrarily shaped mesh but for that i need that vertex "in the rear" that is last vertex on a ray direction (the "exit" vertex).

    Little ASCII art:

    example cube mesh, could be any shape
    _________
    |..............|
    V2------V1-----RD-------C
    |________|

    C - camera position
    RD - ray direction (C-V1)
    V1 - ray entry vertex
    V2 - ray exit vertex

    Minor side note : everything is calculated in object space.

    Oh also the mesh is fully convex, no dings or dents so ray won't go outside of volume before reaching last vertex
     
    Last edited: Dec 28, 2020
  2. highFlylowFlow

    highFlylowFlow

    Joined:
    Nov 27, 2019
    Posts:
    15
    Sorry to bug, but if possible please reply @bgolus
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Short version: You can't, because the GPU doesn't know where the exit is! It only knows the position of the triangle surface you started on.

    Long version: As you noted, for simple shapes, like a cuboid, you can use an analytical form of the shape to calculate the exit. But you can only do this if you've ensured the mesh and the analytical shape match. Basically, you've done some pre-calculation and/or hand authored setup to provide the shader with the needed information.

    For arbitrary meshes, you need to do the same. But since you can't (easily) represent an arbitrary mesh in an analytical form, you need something else. For truly arbitrary meshes, you'd probably need to calculate a 3D SDF for your mesh and store it in a 3D texture. Then you need to be marching through that texture to find the exit distance for the ray your tracing/marching. There are some example tools for generating SDF textures scattered across the internets. This technique has one major issue that the thin edges will always be a little off as you'll need to have some bias so you can make sure your starting ray position isn't outside the more coarse SDF, or you need to use a ton of memory on a very high resolution SDF, which is not advised.

    However there's one more trick if you're limiting yourself to convex shapes. You can use a depth texture. For this you would need to render your own depth texture of only the back faces of your single mesh to a render texture. This is relatively cheap, and as long as you're not doing any refraction can give you the max ray length with a single texture sample and a bit of math. Just subtract the starting position linear depth from the custom depth texture depth for that pixel, and divide by the ray . Optionally sample the camera depth texture too to handle your volume intersecting with the world. One note here, depth is not the same thing as distance, so you need to adjust the depth by the view space ray angle compared to the forward vector. That sounds scarier than it is, as it's really just dividing the linear depth difference by the dot product of the normalized ray direction and the normalized camera forward vector, the later if which you can easily grab from the
    UNITY_MATRIX_V
    .
     
    highFlylowFlow likes this.
  4. highFlylowFlow

    highFlylowFlow

    Joined:
    Nov 27, 2019
    Posts:
    15
    I suspected this will be the case, i'll go for SDF then. I don't care about mesh as long SDF can fit inside it.