Hi All,

I've been thinking about the various classes and relationships that
we'll need to support both the front end API for shader composition,
and the backend implementation of it, and my current thoughts are:

1) The ShaderSet I've been discussing over my last few post should be renamed,
    my current preferred name is ShaderComponent.

2) Rather than ShaderComponent (was ShaderSet) have the details of how to
    inject code into the shader main for each of the vertex, geometry
and fragment
    mains, I now feel it would be more managable to move injection support into
   osg::Shader.

   This would mean that ShaderComponent would then just have a list of
one or more
   osg::Shader.  These Shaders would then be grouped into ones that affect the
   vertex, geometry and fragment programs.

   The osg::Shader class would have some new API for setting up the inject code,
   this could be empty/inactive in a default constructed osg::Shader,
so wouldn't
   affect how we use osg::Shader/osg::Program right now.  It's only when shader
   composition comes into play will these extra fields be queried.

3) StateAttribute would "have a" ShaderComponent that implements the
   shader functionality, this ShaderComponent would typically be shared between
   the same type of StateAttribute.  The StateAttribute attribute
would also provide
   osg::Uniform that pass in the values to the associated ShaderComponent, these
   osg::Unfirom will be applied by the existing
StateAttribute::apply(..) method.

   This is approach I've been discussing before (save for the ShaderSet rename.)

4) osg::State will maintain a current list of enabled ShaderComponent's, this
    list of pointers will form a key to search for the appropriate osg::Program
    to apply to achieve that functionality.  The way that the osg::Program will
    be wrapped up and cached is within a ShaderAssembly.   osg::State
    would internally manage the creation of ShaderAssembly, and cache of these
    and apply the osg::Program they contain.

    Lazy state updating in osg::State will seek to minimize the times that
    the state is changed between ShaderAssembly.  When the set/list of enabled
    ShaderComponent's changes a the appropriate ShaderAssumbly for this set
    of ShaderComponent is then lookup in the ShaderAssembly cache.  If
    non apporpriate ShaderAssembly is found then the ShaderComposer is
    invoked to create a new ShaderAssembly which is then cached and made
    current.

 5) A ShaderAssembly is an internal implementation class so not something
     a user would normally worry about, only the ShaderComposer or
     subclasses from it would need to know about it.

     A ShaderAssembly has the final osg::Program that is applied to OpenGL,
     this osg::Program is composed on the osg::Shader's provided by the
     osg::ShaderComponent, and also an automatically created osg::Shader
     main for each of the vertex, geometry and fragment parts osg::Program.

     The automatically generated shader mains are wrapped up in a ShaderMain
     class that has a list of osg::Shader that contribute to it, these
osg::Shader
     are pulled in from the ShaderComponent's that are associated with the
     ShaderAssembly.  The individual osg::Shader that assigned to a ShaderMain
     provide the code injection details that enable the ShaderComposer to create
     the final main() code that gets placed in the ShaderMain's automatically
     generated osg::Shader.

     The ShaderAssembly contains a ShaderMain for each of the vertex, geometry
     and fragment programs.  Pulling all the Shaders, both provided by the
     ShaderComponent and the automatically generated ones in the three
     ShaderMain to create the final osg::Program.

     It will be possible to share ShaderMain between multiple ShaderAssemly, and
     this will be desirable as often we will just enable/disable a
mode that affects
     only the vertex shaders parts, or just the fragment shader parts,
so if we are
     able to share then we only need create a new ShaderMain for the part that
     changes, the rest can be reused from a cache of ShaderMain (that will be
     provided by osg::ShaderComposer).

     Like ShaderAssembly the ShaderMain is an implementation detail that most
     end users need not use directly or worry about.  It's only osg::State and
     osg::ShaderComposer (or subclasses from it) that will directly
deal with them.

 6) ShaderComposer will manage a cache of ShaderAssembly, and access to
     this cache and the automatic creation of new ShaderAssembly when a
     new combination of enabled ShaderComponent is requested.  When a
     a new ShaderAssembly is created the ShaderComposer querries the
     ShaderComponent to work out what ShaderMain it needs to create, and where
     possible to pull these in from a cache of ShaderMain.

     osg::State "has a" ShaderComposer, and will defer most of the shader
     composition functionality to it.  Users will be able to subclass from
     ShaderComposer to provide their own custom schemes for creating and
     managing the required osg::Program.  Such as subclass could even
     roll their own ShaderMain/ShaderAssembly classes as we might well
     be able to hide these implementation details entirely within the
ShaderComposer
     base class.

 7) In terms of ease of design and management it would be easiest for use to
     by able to assume that ShaderComponent and the osg::Shader they contain
     are all constant.  If a user want to change the shaders they they create a
     new osg::Shader and a new ShaderComponent for them rather than reuse
     an existing one and tweak it.

     We could possible enforce that const behaviour by having a toggle in
     ShaderComponent and osg::Shader that once switched on will make these
     classes ignore changes to them, or at least warn of the change might
     break the ShaderAssembly cache.

     The alternative being able to make the const assumption would be for us
     to implement a dirty count in Shader and ShaderComponent such that
     any associated ShaderAssembly would have to be recreated.  Perhaps
     this might not be too complicated to implement, but wouldn't be without
     a CPU overhead in checking for shader components.

  8) ShaderComponent would provide guidance on what traditional fixed
      function gglEnable/glDisable GLenum's that take over the role of,
      these GLenums we set right now via osg::StateSet::setMode(..).  The
      guidance provided by ShaderComponent will enable osg::State to know
      which modes to redirect to enabling the associated ShaderComponent
      and which should be ingored or still passed on to OpenGL via
      glEnable/glDisable.


OK. That's my current thoughts...  I'm getting reasonably comfortable
with the different parts, not everything is settled but I'm probably
far enough along now to start doing
some coding up which hopefully get a chance to start tackling over the
next couple of days.  It's school holidays right now though so I'm
looking after my brood for most of today, so don't expect too many
check-in's right away.

Let me know your thoughts/suggestions.

Robert.
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to