Hi all,
With the pragmatic shader one could implement multiple lights and other
repetitive constructs like this:
-- start of shader code --
#pragma import_defines ( LIGHTING, LIGHT0, LIGHT1 )
#ifdef LIGHTING
#ifdef LIGHT0
uniform vec4 u_LightColor0;
#endif
#ifdef LIGHT1
uniform vec4 u_LightColor1;
#endif
varying vec4 basecolor;
void light( in vec4 lightColor, inout vec4 color );
#endif
void main(void)
{
basecolor = gl_Color;
#ifdef LIGHTING
#ifdef LIGHT0
light( u_LightColor0, basecolor);
#endif
#ifdef LIGHT1
light( u_LightColor1, basecolor);
#endif
#endif
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
-- end of shader code --
... and to enable both lights:
stateset->setDefine("LIGHTING");
stateset->setDefine("LIGHT0");
stateset->setDefine("LIGHT1");
The problem with this approach is that nobody really knows in advance how many
more lights will be needed. Moreover, the shader can get heavily bloated when
more and more lights are added. As a solution I would like to propose a new
#pragma construct:
#pragma repeat_begin( DEFINE_IDENTIFIER${SubstitutionParameter} )
(shader code block)
#pragma repeat_end()
... and the shader code supporting arbitrary number of lights would then look
like this:
-- start of shader code --
#pragma import_defines ( LIGHTING, LIGHT${Member} )
#ifdef LIGHTING
#pragma repeat_begin( LIGHT${Member} )
uniform vec4 u_LightColor${Member};
#pragma repeat_end()
varying vec4 basecolor;
void light( in vec4 lightColor, inout vec4 color );
#endif
void main(void)
{
basecolor = gl_Color;
#ifdef LIGHTING
#pragma repeat_begin( LIGHT${Member} )
light( u_LightColor${Member}, basecolor);
#pragma repeat_end()
#endif
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
-- end of shader code --
... where ${Member} is a substitution parameter and LIGHT is define identifier.
Then with:
stateset->setDefine("LIGHTING");
stateset->setDefine("LIGHT${0}");
stateset->setDefine("LIGHT${1}");
stateset->setDefine("LIGHT${5}");
... where ${0}, ${1}, ${5} are substitution values, osg would produce following
shader code:
-- start of shader code --
#define LIGHTING
#define LIGHT0
#define LIGHT1
#define LIGHT5
#ifdef LIGHTING
uniform vec4 u_LightColor0;
uniform vec4 u_LightColor1;
uniform vec4 u_LightColor5;
varying vec4 basecolor;
void light( in vec4 lightColor, inout vec4 color );
#endif
void main(void)
{
basecolor = gl_Color;
#ifdef LIGHTING
light( u_LightColor0, basecolor);
light( u_LightColor1, basecolor);
light( u_LightColor5, basecolor);
#endif
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
-- end of shader code --
Before I do any coding I'd like to know if proposed solution would be of any
use to the osg community? Or maybe there is a better way? I'm currently solving
these kinds of problems with uniform arrays, but unfortunately, the uniform
array has its own max number of elements and the management code of such
approach tend to be complicated...
Cheers,
Robert Milharcic
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org