I need a little bit of help with a few shaders. This is the problem. I have a simulation with several spotlights that are all moving in an environment. I can’t use the AutoShader for that because that takes too much performance, so I have a shader that does the lighting. The shader works okay:
//Cg
/*
spotlight_mycar.sha
*/
void vshader(
in float4 vtx_color : ATTR3,
out float4 l_color : COLOR0,
in float4 vtx_texcoord : ATTR8,
out float4 l_texcoord : TEXCOORD0,
uniform float4x4 trans_model_to_view,
out float4 l_eye_position : TEXCOORD1,
uniform float4x4 tpose_view_to_model,
out float4 l_eye_normal : TEXCOORD2,
in float3 vtx_normal : ATTR2,
in float4 vtx_position : ATTR0,
out float4 l_position : POSITION,
uniform float4x4 mat_modelproj
) {
l_position = mul(mat_modelproj, vtx_position);
l_eye_position = mul(trans_model_to_view, vtx_position);
l_eye_normal.xyz = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));
l_eye_normal.w = 0;
l_texcoord = vtx_texcoord;
l_color = vtx_color;
}
void fshader(
in float4 l_eye_position : TEXCOORD1,
in float4 l_eye_normal : TEXCOORD2,
in float4 l_texcoord : TEXCOORD0,
uniform sampler2D tex_0,
uniform float4x4 attr_light0,
uniform float4x4 attr_light1,
uniform float4 attr_lspec1,
out float4 o_color : COLOR0,
in float4 l_color : COLOR0,
uniform float4 attr_color,
uniform float4 attr_ambient,
uniform float4 attr_colorscale
) {
float4 result;
float4 texcoord0 = l_texcoord;
// Fetch all textures.
float4 tex0 = tex2D(tex_0, texcoord0.xy);
// Correct the surface normal for interpolation effects
l_eye_normal.xyz = normalize(l_eye_normal.xyz);
// Begin view-space light calculations
float ldist,lattenv,langle,lshad;
float4 lcolor,lspec,lpoint,latten,ldir,leye;
float3 lvec,lhalf;
float4 tot_diffuse = float4(0,0,0,0);
tot_diffuse += attr_ambient;
// Spot Light 0
lcolor = attr_light0[0];
lspec = lcolor;
latten = attr_light0[1];
ldir = attr_light0[2];
lpoint = attr_light0[3];
lvec = lpoint.xyz - l_eye_position.xyz;
ldist = length(lvec);
lvec /= ldist;
langle = saturate(dot(ldir.xyz, lvec));
lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);
lattenv *= pow(langle, latten.w);
if (langle < ldir.w) lattenv = 0;
lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec));
tot_diffuse += lcolor;
// Directional Light 1
lcolor = attr_light1[0];
lspec = attr_lspec1;
lvec = attr_light1[3].xyz;
lcolor *= saturate(dot(l_eye_normal.xyz, lvec.xyz));
tot_diffuse += lcolor;
// Begin view-space light summation
result = float4(0,0,0,0);
//result += tot_diffuse * attr_color;
result += tot_diffuse * l_color;
result = saturate(result);
// End view-space light calculations
result.a = 1;
result *= attr_colorscale;
result.rgba *= tex0.rgba;
o_color = result * 1.000001;
}
I load the shader and assign it to a number of nodepaths so that they are properly lit:
shader = Shader.load("spotlight_mycar.sha", Shader.SL_Cg)
if self.segs != None:
for obj in self.segs:
obj.set_shader(shader)
However, when more spotlights are created, then they replace attr_light0 in the shader. I could solve that by adding attr_light1, attr_light2 etc. but I don’t know in advance how many spotlights there will be. So what I would like to have is a mechanism where I can make the shader work for specific spotlights, for example by using something like:
self.rheadlight = base.camera.attachNewNode( Spotlight( “spotlight” ) )
obj.set_shader_input(‘attr_light0’, self.rheadlight )
Is there a way to assign a specific spotlight to the shader because now it just grabs the first spotlight it can find?