How can I create Volume Density based on the thickness of the object?

I saw this post from 2018 Volumetric scatter density - ray length

And it was the answer to my solution, and I even got the script running without any issues (After some edits)

Edited script that runs without errors in blender 2.9
https://hatebin.com/osaketazij

What Im getting at, is that I want to create a Scatter Density based on the thickness of the object.

Im doing this because I want a realistic atmosphere for my Planet Render

As you can see, Im using the script, and Im trying to use the factor for the density, but I dont think Im using it correctly…

And as you can see aswell, the planet has a very sharp edge… Theres no fading or anything, and I want to have the volume fade outwards, with the inner volume having more density and less as you get to the surface

Also I tried using this “point density” node thing, which Ive never heard of until now…

Unfortunately, although its subtle and I kinda like its effect, its not really what I want…

I looked for similar thing some time ago:

Here is an OSL:

shader volume_meshproximity(
    vector Point = P,
    int Iterations = 1,
    output float Min_Distance = 0.0,
    output float Max_Distance = 0.0,
    output float Avg_Distance = 0.0
    ) {

    float x;
    float y;
    float z;
    vector rand;
    float scale = 5000.0;
    float sum_dist = 0.0;
    float max_dist = 0.0;
    float min_dist = 0.0;
    float Distance = 0.0;

    for (int loop = 0; loop < Iterations; loop++)
    {

        rand = noise(Point*scale,loop*scale);
        x = rand[0] - 0.5;
        y = rand[1] - 0.5;
        z = rand[2] - 0.5;

        if(trace(Point,normalize(vector(x,y,z))))
        {
            getmessage("trace", "hitdist", Distance);
            //getmessage("trace", "N", Normal);
            //getmessage("trace", "hit", Hit);
        }

        if (loop == 0)
        {
            sum_dist = Distance;
            max_dist = Distance;
            min_dist = Distance;
        }
        else
        {
            sum_dist = sum_dist + Distance;

            if (Distance > max_dist)
            {
                max_dist = Distance;
            }

            if (Distance < min_dist)
            {
                min_dist = Distance;
            }
        }
    }

    Max_Distance = max_dist;
    Min_Distance = min_dist;
    Avg_Distance = sum_dist / Iterations;
}
2 Likes

Can you show me a basic setup of this node? I want to make sure I get it right.

Specifically the one from your post in which you mentioned you could replace the outline with a transparent shader

Top nodes are for manual empty control, so you don’t need them.
The bottom nodes are what is important. The 3 selected nodes (Divide, Color Ramp, Emission) are the main control. Play with the values and you will get it.
Bottom Volume Scatter and Absorbtion are optional. You should also swap Emission node for Volume Scatter, as planet atmosphere is not emissive.

Bear in mind, that this shader is expensive and your rendering times can be long.

2 Likes

Thanks, this is perfect

For your case, getting the depth of a sphere, you don’t have to use scripts, which is nice because you can use GPU rendering when not using OSL:

You’ll want scale applied, with the proper radius entered in the value field (for mathematically perfect operation, but feel free to tune to eye instead) and an object origin at the center of the sphere.

What you’re doing is creating a vector in the plane of the object and then just getting the bit of the vector pointing in the same direction as the camera. That’s the distance from the camera plane, running through the object origin, to the sample. Because this plane runs through the center of your object, the actual distance from one point of the sphere to the other is twice this number.

I should add, it’s not really correct for perspective, but that’s unlikely to be noticeable.

3 Likes

I already found a solution for OSL. Also I can use OSL and GPU rendering together.

thanks anyhow though

That’s a neat trick!
With additional divide nodes plugged after absolute you can control density and color much better.

OP, I doubt that you can have OSL with GPU support. This feature is pretty much WIP at this point. @bandages solution is several times faster in rendering times if you need a sphere shaped atmosphere.

2 Likes

I just realized, it’s not quite right for volumes. Should be right for shells, but volumes have internal samples, for which the distance to the plane isn’t the distance through the sphere.

That’s fixable with a bit more math, but I’ve got some chores, I’ll show later.

For aproximating thin layer of atmosphere in OPs example sampling internal volume is not that necessary I think. But for see-through volumes you might be right. After all OSL script is doing that.

Obviously, if it’s what you want, then that’s good :slight_smile:

To do what OP explicitly wanted, I would really do it like that-- volumetrics already have a cumulative effect from the screen space depth of the volumetric. Instead, I might, at most, do a little bit of mapping of the density based on the distance from the center of the object (which some people get with object coords -> gradient texture, but I usually get from object coords -> vector math/length.)

I tried something out to do what OP was explicitly asking for, correcting for the positions inside the sphere, but it’s starting to hurt my head, and isn’t elegant like what I offered before, so I’m going to call it a night :slight_smile:

1 Like

Okay, here we go. Just needed to sleep on it:

This doesn’t require any particular scale for the object, since it uses world space coordinates (the object coords are just for locating the center of the sphere), but it still needs to know the sphere’s world-space radius. (If you want to just use default-ish spheres with object transforms, you can build that into the mat by looking at the distance between 0,0,0 and 1,0,0 object coords in world space.)

It’s still not perspective correct, but correct for orthogonal cameras; you could do perspective correct, but it’s more math, and the difference isn’t going to be noticeable.

I’ve made an interior sphere, just as part of testing it, but it should be noted that the distance you’re getting is not the distance through just the “atmosphere” but the distance through the entire sphere.

I actually wasnt able to replicate this effect myself.

Copied the nodes to the point, and it just doesnt work

Look closely at the Color Ramp node.
In my example there are two additional sliders at the very right of the ramp. The first missing one have balck value and second one - white.
I belive this should fix your issue.