Hi Robert,

This seems more complicated than needed.
Why not pass the number of lights as a compile time constant

#pragma import_defines (NUM_LIGHTS)

shader_state->setDefine("NUM_LIGHTS",12);

and use uniform arrays:

uniform vec4 u_LightColor[NUM_LIGHTS];

for (int i = 0; i < NUM_LIGHTS;++i)
{
    light+=calcLight(u_LightColor[i], ...):
}

I feel your approach will bloat the preprocessor code path and will complicate the use.



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
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to