[osg-users] Multiple lights in a scene

David Callu ledocc at gmail.com
Tue Apr 19 00:42:52 PDT 2011

Hi Chris, Hi Jean-Sébastien

I just ending a similar work for a client and i could provide some advice on
the subject.
First, I derived from osg::LightSource to osgLighting::LightSource (that
could contain many light, not only one as osg::LightSource) and add a
cullCallback to do a similar job of
I create a osgLighting::LightGroup (not a node) which contain light
parameter (ambient, diffuse, position, direction ...)
in uniforms arrays, and be shared by all lights
I derived from osg::Light to osgLighting::Light that contain an
osgLighting::LightGroup to store parameter in it.

Shader is handle by a shader generator so I can't help you on this point.
But I conclude after some test that per pixel lighting is not a choice.
If you want apply shadow per light, you have to combine each light/shadow
in the pixel shader. you can't compute light in vertex shader, then pass
result of each light
in pixel shader, and apply shadow on each light result. if you have 40
lights in you scene.
you have to pass 40 vec3 from vertex shader to pixel shader ouch!!!
according to Real-Time Rendering 3ed,
Shader Model 4 have 16 interpolation registre between Vertex and
Geometry/Pixel Shader and
32 between Geometry and Pixel Shader.

About deferred shading, this is my first reflex to not pay the Z complexity
of the scene.
But OpenGL allow only 8 texture target to render in, so 8*4=32 values.
We can use 3 for eye position, 3 for normal. This let's us with 26 value to
pass light direction/position.
That is largely under the need to handle more that 8 lights.
I read an article about Unreal Engine that push the 3 nearest lights in RTT,
and all others lights are combined in one, so only 4 light is pass to RTT,
then computed in deferred shader.
I have to dig this way ...

Still according to Real Time Rendering 3ed, if you don't write the
gl_FragDepth in your shader, recent hardware
discard automatically the pixel computation if pixel in frame buffer is
front of the incoming pixel.
You can use OSG_DEFAULT_BIN_SORT_MODE=SORT_FRONT_TO_BACK to help hardware to
do the job.

I am in negotiation with my client to put osgLighting and osgGLSL (the
shader generator) in OpenSource.
But this will not happen before summer I think. Many people to convince that
OpenSource is the good way for every body.

David Callu

2011/4/19 Jean-Sébastien Guay <jean-sebastien.guay at cm-labs.com>

> Hi Chris,
> First of all, I have to commend you on all the work you've put into doing
> this. You obviously put a lot of thought and research into your problem, and
> explored multiple avenues before posting, which I have to admire!
> I've personally never needed more than the 8 light sources the fixed
> pipeline gave me, so I've always used the built-in gl_LightSource[i]
> structure and osg::LightSource+osg::Light to manage my lights. I have a
> mechanism in place that lets me reuse light IDs when lights get turned on or
> off (a light turned off frees its light ID, and a light turned on will take
> the first available light ID), and this uses IDs 0-7, which has been
> sufficient for me. Add to that the fact that OSG's built-in shadow
> techniques support casting shadows from only one light, and I've never
> really had a need (personally or from client requirements) to go further.
> But that's not to say it won't happen.
> What I'd say in response to your question is, I think you have a good idea
> of what is the best solution to your problem (solution 1), but it requires
> some small changes to OSG itself in order to be feasible. So what prevents
> you from proposing these changes? Robert hasn't been against making some
> methods virtual when needed in the past, and even deeper changes will be
> possible when they're justified.
> About the CullVisitor, I don't understand what you mean about not
> recognizing new classes. First of all, sure, you could add new classes to
> its interface, but even if not, you can always, in the
> accept(osg::LightSource&) method, check with a dynamic_cast if the
> lightSource is of your derived class:
> virtual void accept(osg::LightSource& ls)
> {
>  if (dynamic_cast<myOwnLightSource*>(&ls) != 0)
>  {
>    // My light source subclass.
>  }
>  else
>  {
>    // Plain old osg::LightSource
>  }
> }
> But whatever you decide, I think you shouldn't rule out changes to the core
> OSG. The fixed pipeline is out, and shaders are in, and if OSG could be made
> to support its own osg_LightSource[i] uniforms, with indices limited only by
> shader memory (while not ruling out the possibility that the first 8 of
> those be mapped to the fixed pipeline light sources if the fixed pipeline is
> available) then that would be very nice indeed.
> I'll just add one last note, another way to deal with many light sources
> would be to do deferred shading, maybe you should look this up. It all
> depends on what you're doing, but deferred shading has the advantage that
> all complex lighting calculations (per pixel lighting, normal mapping, etc.)
> happen in screen space only once per visible pixel, instead of possibly
> happening many times per pixel and being overwritten (because of z order).
> Hope this helps, and I hope you'll be able to show us some really cool
> stuff in the near future,
> J-S
> On 18/04/2011 10:09 PM, SkullCheck wrote:
>> Hi Gordon,
>> I hope those puns were intended, in any case, they brightened my day ;)
>> I did search the archives and found one reference to the osgmanylights
>> tutorial, but unfortunately it is no longer on the site that it was
>> linked to, does anyone have a copy of that tutorial lying around in
>> their archive? The old link was:
>> http://www.fx.clemson.edu/~acnatha/devnull/osg/osgmanylights.tar.gz
>> I was however able to successfully implement pixel-based lighting in a
>> fragment shader with as many lights as desired (up to shader memory
>> limits of course). I basically just defined my own uniform array of
>> gl_LightSourceParameters in the shader program. The values of these
>> custom lights are controlled with uniforms which, when wrapped up in a
>> LightUniforms class provides an API identical to osg::Light. A
>> LightShader class, derived from osg::Shader, provides an interface for
>> setting the number of lights which basically just does a search and
>> replace of a special string (i.e. NUM_LIGHTS) in the shader source and
>> then forces a recompilation of the shader program. This all works
>> fine.
>> The problem comes however in positioning the lights. If I understand
>> correctly, OSG uses a LightSource placed in the scenegraph to modify
>> the position of its associated Light according according to its parent
>> transformation(s). This gets done by the PositionalStateContainer
>> which gets added to the RenderStage during cull traversal in
>> CullVisitor::accept(LightSource) ->
>> RenderStage::addPositionedAttribute(). I was thinking about a couple
>> of solutions to this:
>> 1. Derive my own classes from osg::Light and osg::LightSource. This is
>> problematic for a number of reasons:
>> - CullVisitor, being a Visitor class, cannot be expanded (without
>> modifying its interface) to recognize new classes (one of the
>> tradeoffs for the Visitor pattern). So it will not recognize my
>> derived LightSource class, if I understand the Visitor pattern
>> correctly.
>> - Deriving from osg::Light, which calls fixed function opengl lighting
>> calls, causes GLMode errors for light numbers>= GL_MAX_LIGHTS.
>> 2. Do not derive my own classes osg::Light and osg::LightSource, but
>> instead make my LightSource-type class subclass from osg::Group
>> directly, override the traverse() method, extract the localtoWorld
>> transform from the visitor object and and based on that set the
>> position and spotdirection on the (non osg derived) Light. However,
>> this has some other side effects:
>> - we have a shadow class, based on osg::ShadowTechnique, which relies
>> on the PositionalStateContainer mechanism described above to position
>> the shadow projectors to coincide with the osg::Light. Not using the
>> osg::Light will not trigger this mechanism.
>> At the moment I'm leaning toward solution 2, but then that would force
>> me to adapt the shadowing class (which I inherited and it isn't
>> pretty). I would like to get solution 1 to work though, but I can't
>> figure out a way to use the osg::Light/LightSource interface and
>> prevent it from calling the opengl fixed function API. It would be
>> nice if all the osg::Light methods were virtual, then I could just
>> derive my LightUniforms based class from osg::Light.
>> I did read in the OSG QSG, page 69:
>> "OSG lets you use more light sources than the underlying OpenGL
>> implementation supports, but this is beyond the scope of this book."
>> Is there another resource whose scope this isn't beyond? Does this
>> have to do with multiple RenderStages, which I suspect is in the
>> osgmanylights example?
>> Thanks,
>> Chris
>> On Tue, Nov 18, 2008 at 8:05 PM, Tomlinson, Gordon
>> <GTOMLINSON at overwatch.textron.com>  wrote:
>>> Search the mailing list archive will find many illuminating answers to
>>> this
>>> type of question
>>> Opengl only supports 8 active light sources thus OSG supports one 8
>>> active
>>> light sources
>>> Also search the Opengl sites for more enlightenment
>>> Gordon
>>> __________________________________________________________
>>> Gordon Tomlinson
>>> Product Manager 3D
>>> Email  : gtomlinson @ overwatch.textron.com
>>> __________________________________________________________
>>> (C): (+1) 571-265-2612
>>> (W): (+1) 703-437-7651
>>> "Self defence is not a function of learning tricks
>>> but is a function of how quickly and intensely one
>>> can arouse one's instinct for survival"
>>> - Master Tambo Tetsura
>>> ________________________________
>>> From: osg-users-bounces at lists.openscenegraph.org
>>> [mailto:osg-users-bounces at lists.openscenegraph.org] On Behalf Of dasari
>>> pavan kumar
>>> Sent: Tuesday, November 18, 2008 12:50 PM
>>> To: osg-users at lists.openscenegraph.org
>>> Subject: Re: [osg-users] Multiple lights in a scene
>>> Hi,
>>>       I am relatively new to using Lights in openscenegraph. I would like
>>> to
>>> have a single light replicated 100 times at different places (The
>>> situation
>>> is something like this. I need to light all the rooms in an apartment.
>>> however every light is of the same ambient and diffuse color). But the
>>> lights are not being rendered in the scene. Can anyone help me with this
>>> situation ?
>>> I have created a LightSource with certain light properties and attached
>>> it
>>> to a group.
>>> Now I created different MatrixTransforms and added this lightGroup to
>>> these
>>> MTs as child.
>>> However cant see the result. If this is not the way it is to be done,
>>> plzz
>>> help me out with the solution.
>>> thanx in advance,
>>> pavan
>>> --
>>> _______________________________________________
>>> osg-users mailing list
>>> osg-users at lists.openscenegraph.org
>>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>>  _______________________________________________
>> osg-users mailing list
>> osg-users at lists.openscenegraph.org
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> --
> ______________________________________________________
> Jean-Sebastien Guay    jean-sebastien.guay at cm-labs.com
>                               http://www.cm-labs.com/
>                    http://whitestar02.dyndns-web.com/
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/attachments/20110419/7101d15e/attachment-0004.htm>

More information about the osg-users mailing list