Shadow Volumes and Volumetric Lights

After that big thread you guys made up regarding doom 3,I decided to read up a bit on Shadow Volumes. I just read an article on gamasutra regarding Shadow Volumes and I was thinking if Volumetric Lights can be done in a similar method (similar regarding the calculation of the shadow volume). We can calculate (or even generate it … like a aimple cone for spotlights) a “Light Volume” similarly for a Light Object.

If I understand correctly opengl calculates the fog right after a texel is got and before the fragement tests (is this right?)
And can fog be enabled/disabled at any time?

My method:
First render the scene normally.
Next render the Light Volumes culling out the front faces with fog enabled.
Then render the Light Volumes culling out the back faces with fog enabled but a darker fog color.

Maybe we can turn blending on after the first step to make things look better.

If this can be done then we can have Light Volumes for any arbitrary shaped light.
…and how does the shadow volume deal with holes in objects generating shadows?

(I hope I havent written a load of crap)

[This message has been edited by tarantula (edited 06-13-2002).]

Originally posted by tarantula:
[b]
My method:
First render the scene normally.
Next render the Light Volumes culling out the front faces with fog enabled.
Then render the Light Volumes culling out the back faces with fog enabled but a darker fog color.

[This message has been edited by tarantula (edited 06-13-2002).][/b]

I think you need to detail your steps further. What’s the point of culling friont faces, then render, cull back faces, then render.

Why not render normaly with the fog.
Turn fog off. Turn light off.
clear stencil.
set up the stencil to pass only when z passes and stencil passes. stencil passes when stencil fragment is 0.
When stencil passes, stencil becomes 1.
A “dark color” front face is rendered while in blend mode. dark color may be {0, 0, 0, 0.5)

This may not look realistic, but better than more complex methods.
Also, since blending will be used (source_alpha, 1-source_alpha, …
V-man

Originally posted by V-man:
I think you need to detail your steps further. What’s the point of culling friont faces, then render, cull back faces, then render.

The correct value for the intensity of light contributed by a Volumetric Light at any pixel can be calculated by integrating the light color density along the line passing our eye and the pixel with bounds being the points(say P,Q) where the line intersects the Light Volume.

Let us assume the function is 1ColorDensity.
Then the integration result will be ColorDensity
distance.
Which is ColorDensity*(dist of P from eye - dist of q from eye). (assume P is farther)
I can approximate this with ColorDensity*(dist of P from eye) overlayed with (1-ColorDensity)*(dist of Q from eye) with appropriate blending and the fogColorDensity being ColorDensity and 1-ColorDensity.

I hope this explains.
Currently this will not do Light attenuation.

So will my method work?

[This message has been edited by tarantula (edited 06-13-2002).]

Originally posted by tarantula:
[b]
Let us assume the function is 1ColorDensity.
Then the integration result will be ColorDensity
distance.
Which is ColorDensity*(dist of P from eye - dist of q from eye). (assume P is farther)
I can approximate this with ColorDensity*(dist of P from eye) overlayed with (1-ColorDensity)*(dist of Q from eye) with appropriate blending and the fogColorDensity being ColorDensity and 1-ColorDensity.

I hope this explains.
Currently this will not do Light attenuation.

So will my method work?

[This message has been edited by tarantula (edited 06-13-2002).][/b]

I’m not sure what the appropriate blend
equation you intend to use is, but here’s one that resembles your idea.

(backgroundcolor-backpolycolor)+frontpolycolor

to implement that with OpenGL requires an extension (part of 1.2 I think)

glEnable(GL_FOG);
Render(everything_normally);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_SUBSTRACT);
glBlendFunc(GL_ONE, GL_ONE);
glColor3f(0.0, 0.0, 0.0);
Render(backpolygons_of_shadowVolumes);
glBlendEquation(GL_FUNC_ADD);
Render(frontpolygons_ofshadowvolumes);

Don’t forget to cross your fingers!

V-man

>>>Currently this will not do Light attenuation.
<<<

opengl computes the lighting. You need to give it the right attenuation numbers (linear, constant & quadratic). the fog and lighting are separate as far as gl is concerned.

V-man

You’ve got that the wrong way round - add the backfaces in, then subtract the front faces. It’s the same technique used for volumetric fog on enclosed volumes - and yes, it does look rather nice…shafts of light through dark rooms…but that’s about it.

This stuff might interest you, it is related in my opinion.
http://www.nothings.org/computer/vfog/shots.html

V-man, I was referring to the Volumetric Light attenuation.I think that may be achieved if I assign alpha values to the Light Volume mesh : 1.0 near the light and 0.0 at the other end. else it’ll look odd that that intensity of light increases with distance as usually that Light Volume spreads out like a cone.

Dorbie thanks for the link.I havent gone through his algorithm yet but it needs a additional pass for every front face and he uses stencil.I wonder why coz my method doesnt need a stencil buffer.

Originally posted by knackered:
You’ve got that the wrong way round - add the backfaces in, then subtract the front faces. It’s the same technique used for volumetric fog on enclosed volumes - and yes, it does look rather nice…shafts of light through dark rooms…but that’s about it.

For shafts of light in a dark room, the other way around will work. I was thinking about being outdoors with a foggy atmosphere.
In that case, the fog inside the shadow volume will not be directly lit by the light source and we might as well substract it.

Now there is a problem of whether you are inside or outside the shadow volume (light volume). Clamping with the near plane (near 0) will do.

For the light attenuation (dark room with light comming in):
both the light spreading and the diffusion effect of the fog will effect the light.
Let’s assume we have a light cone. You can use

1/r^2-fogfactor*h where r is the radius of the
light cone and h is the distance the light has travelled.

I get the feeling Im missing something here.

V-man

Originally posted by V-man:
[b]
Let’s assume we have a light cone. You can use

1/r^2-fogfactor*h where r is the radius of the
light cone and h is the distance the light has travelled.

I get the feeling Im missing something here.

V-man[/b]

V-man, where should I use the expression 1/r^2-fogfactor*h ? For the alpha values of vertices the Light Volume?

Light Volumes unlike shadow volumes do not always extend to infinity. It depends on the type of the Vol light.The Light Volume Mesh extends only until the point where the light is attenuated to zero.If the light moves ,the whole Light volume just moves along with it.And the Light Volume has two sets of vertices one near the light source that trace the shape of the light and the other set where light is attenuated to zero.

A lot of problems are still there.How should I deal with clamping?Should I draw the main scene last? And then occluders for the volumetric light?(welcome volumetric shadows!)

OK, I will give you an idea on how to do it the opengl way, but you may need to sort out the details to make it look accurate.

I suggest you plug in the appropriate variables in the light properties (attenuation)You place a point light at the cones tip (not really the tip, it has to be below the tip) and have it light the entire light cone (the beam)
Compute a vector from each vertex of the beam to the light source and make that the normal for the vertex.
A blending mode of GL_ONE, GL_ONE will have to be enabled.
The beam walls could be made white (same as light)

I’m not sure if you can use this with the fogging technic described above. The fogging technic is pretty much fake.

Do transparent objects get fogged?

V-man

>Do transparent objects get fogged?

fog is no material, it does not go onto objects. its an object itself, a volumetric one, and yes, it is transparent.

V-man,

the issue with transparent objects is summing the terms correctly (and multiple depth values more on that later). You have the object behind the transparency the atmosphere between that object and the transparent one, then the transparency itself then the atmosphere between the viewer and the transparent object. All of this is really an approximation of course. Can you think of a physically transparent object the behaves the way it’s rendered in most OpenGL apps? Maybe a gauze screen would look transparent in this sense.

I think with these approaches transparent objects would be consistent if the occluding fog volumes can be sorted with the transparent depth values. If you can’t sort then there’s the classic issue of having multiple depth values per fragment (which you can’t store) and therefore irresolvable fog contributions and it cannot work, at least for the approaches described in this thread.

Basically I think it works if you are able to sort.

Yeah with transparent objects in the fog volume I’d have to sort the occluding volumes. Then I’d have to alternate between drawing fog volumes and drawing the transparent objects. yuck!

For occluders in the fog volume,the occluding fog volume will be the object + its shadow volume, wheras for transparent objects (or any non shadow-casting object) the occluding fog volume will be the object itself.

One problem I’ll face while drawing these Light and Shadow fog volumes is clamping.The final color values will be wrong if clamping occurs at anytime.I dont like sorting the volumes for this.

Anyway, thanks a lot for your help. I’ll
code this as soon as my exams are over and see what other problems I’ll have.

[This message has been edited by tarantula (edited 06-17-2002).]