Hi, Sounding great so far. A lot to digest! I have a couple of questions.
One thing I am not clear on is how the rules for injecting a Shader into a ShaderMain would work. This is an area I have had difficulty with in my own shader assembly approach. For example, how will it be possible to change the order in which shaders are applied? As a contrived example, I might want to use the material color of a fragment as the input to my lighting shader, and then blend my textures with the result. Alternatively, I might want to first blend all my textures, then use this color as the input to the lighting shader. How would I specify these kind of rules? Another area I am not clear on is how (if at all) we will be able to avoid doing the same calculations many times for a single vertex or fragment. Say, for example, we need the ec position of a vertex as an input to several of our vertex Shaders. Would each shader have to recalculate this value independently? This shouldn't be a major hit to performance in most cases but it is obviously less efficient than just doing the calculation once. Then again, maybe the compiler can figure this out for us. Cheers, Brad -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Robert Osfield Sent: Thursday, 1 July 2010 4:30 PM To: OpenSceneGraph Users Subject: Re: [osg-users] Shader composition, OpenGL modes and custom modes 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 DISCLAIMER:--------------------------------------------------------------------------- This e-mail transmission and any documents, files and previous e-mail messages attached to it are private and confidential. They may contain proprietary or copyright material or information that is subject to legal professional privilege. They are for the use of the intended recipient only. Any unauthorised viewing, use, disclosure, copying, alteration, storage or distribution of, or reliance on, this message is strictly prohibited. No part may be reproduced, adapted or transmitted without the written permission of the owner. If you have received this transmission in error, or are not an authorised recipient, please immediately notify the sender by return email, delete this message and all copies from your e-mail system, and destroy any printed copies. Receipt by anyone other than the intended recipient should not be deemed a waiver of any privilege or protection. Thales Australia does not warrant or represent that this e-mail or any documents, files and previous e-mail messages attached are error or virus free. -------------------------------------------------------------------------------------- _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

