I haven't been able to come up with a good solution for this myself, so I thought I'd ask if anyone else has any good ideas on how to approach this problem. Here's more or less what I'm trying to do and what I've been able to research / think of so far:
I have implemented volumetric light rendering in my engine, and the way you feed atmospheric effects right now is either by a constant global fog (parametrized as optical length), a global height fog (pretty much the same as https://iquilezles.org/articles/fog/) or with a local volume that's parametrized using an AABB and density (which modules the optical length) and also the ability to do falloff in the same way as the height fog (so exponential, towards a user direction). One issue with the volume is that the cutoff at the edges of the volume is quite abrupt, so I'd like to add some feathering to it. An issue with this is that it needs to be integrateble along a ray segment in the same way as the height fog. It turns out that this problem is quite tricky.
Here's the code from https://iquilezles.org/articles/fog/ which computes the global height fog, this is pretty much the same as in my engine so let's use this instead of my re-written version of it. The fogAmount
is essentially computing the optical length from rayOri
towards rayDir
for a known distance
(e.g. surface hit). Note that all it needs are these paramters, and it can analytically figure out the optical length from just that (it looks at height difference change to be able to do it analytically).
vec3 applyFog( in vec3 rgb, // original color of the pixel
in float distance, // camera to point distance
in vec3 rayOri, // camera position
in vec3 rayDir ) // camera to point vector
{
float fogAmount = (a/b) * exp(-rayOri.y*b) * (1.0-exp( -distance*rayDir.y*b ))/rayDir.y;
vec3 fogColor = vec3(0.5,0.6,0.7);
return mix( rgb, fogColor, fogAmount );
}
The problem I'm trying to solve is similar, but I want to be able to, analytically, figure out the optical density if you had a AABB with some amount of feathering at the edge. The function signature is the same, but instead of a
and b
as parameters (these define the height falloff) we'd just have a feather
parameter that represents how far the feathering should be applied inside the volume. Here's a figure of how something like this looks like:
I've not been able to find a good representation to modulate the optical length to make it be numerically integrateable in the same way as Inigo Quilez's height fog. It's possible to find the distance from some point to the surface of an AABB like this:
float distance = length( max( max( aabb.min - point, 0.0f ), max( point - aabb.max, 0.0f ) );
And it would be possible to use that as input to e.g. smoothstep
to modulate the optical length: smoothstep( 0.0f, feather, distance )
but there is no physical point
to do this with, as this is a ray integral. So I guess my "real" question is: is this even possible to solve if this has the form of a ray integral? For height fog à la Inigo Quilez it's possible (it's mentioned in the article that it's possible to derive new such functions by solving the ray integral again with a different set of parameters) but is it also possible to do it in this case as well where we would want to have feathering on the edges of an AABB to change the optical length?
I realize that this is a bit of an odd question that's more exploratory than anything else... and hopefully I was able to explain what the problem was. Any ideas and help are much appreciated! I've run out of good ideas for doing it as a ray integral :-(
I have a gut feeling that this somehow involves computing rate of change based on the feathering and taking the incoming ray direction to modulate it (much like the height fog is doing)...
Thanks for the help!