1 #include "RTShaderSRSSegmentedLights.h"
2 #include "OgreShaderFFPRenderState.h"
3 #include "OgreShaderProgram.h"
4 #include "OgreShaderParameter.h"
5 #include "OgreShaderProgramSet.h"
6 #include "OgreGpuProgram.h"
7 #include "OgrePass.h"
8 #include "OgreShaderGenerator.h"
9 #include "OgreSceneManager.h"
10 #include "OgreViewport.h"
11 #include "OgreMaterialSerializer.h"
12 #include "SegmentedDynamicLightManager.h"
13 
14 #define SL_LIB_PERPIXELLIGHTING                 "SegmentedPerPixelLighting"
15 #define SL_FUNC_TRANSFORMNORMAL                 "SL_TransformNormal"
16 #define SL_FUNC_TRANSFORMPOSITION                   "SL_TransformPosition"
17 #define SL_FUNC_LIGHT_DIRECTIONAL_DIFFUSE           "SL_Light_Directional_Diffuse"
18 #define SL_FUNC_LIGHT_DIRECTIONAL_DIFFUSESPECULAR   "SL_Light_Directional_DiffuseSpecular"
19 #define SL_FUNC_LIGHT_AMBIENT_DIFFUSE               "SL_Light_Ambient_Diffuse"
20 #define SL_FUNC_LIGHT_SEGMENT_TEXTURE_AMBIENT_DIFFUSE   "SL_Light_Segment_Texture_Ambient_Diffuse"
21 #define SL_FUNC_LIGHT_SEGMENT_DEBUG             "SL_Light_Segment_Debug"
22 
23 using namespace Ogre;
24 using namespace Ogre::RTShader;
25 
26 String RTShaderSRSSegmentedLights::Type = "Segmented_PerPixelLighting";
27 Light RTShaderSRSSegmentedLights::msBlankLight;
28 
29 
30 //-----------------------------------------------------------------------
RTShaderSRSSegmentedLights()31 RTShaderSRSSegmentedLights::RTShaderSRSSegmentedLights()
32 {
33     mTrackVertexColourType          = TVC_NONE;
34     mSpecularEnable                 = false;
35     mUseSegmentedLightTexture       = false;
36     mLightSamplerIndex = 0;
37 
38     msBlankLight.setDiffuseColour(ColourValue::Black);
39     msBlankLight.setSpecularColour(ColourValue::Black);
40     msBlankLight.setAttenuation(0,1,0,0);
41 }
42 
43 //-----------------------------------------------------------------------
getType() const44 const String& RTShaderSRSSegmentedLights::getType() const
45 {
46     return Type;
47 }
48 
49 
50 //-----------------------------------------------------------------------
getExecutionOrder() const51 int RTShaderSRSSegmentedLights::getExecutionOrder() const
52 {
53     return FFP_LIGHTING;
54 }
55 
56 //-----------------------------------------------------------------------
updateGpuProgramsParams(Renderable * rend,Pass * pass,const AutoParamDataSource * source,const LightList * pLightList)57 void RTShaderSRSSegmentedLights::updateGpuProgramsParams(Renderable* rend, Pass* pass, const AutoParamDataSource* source,
58     const LightList* pLightList)
59 {
60     if ((mLightParamsList.empty()) && (!mUseSegmentedLightTexture))
61         return;
62 
63     const Affine3& matWorld = source->getWorldMatrix();
64     Light::LightTypes curLightType = Light::LT_DIRECTIONAL;
65     unsigned int curSearchLightIndex = 0;
66 
67     //update spot strength
68     float spotIntensity = 1;
69 
70     // Update per light parameters.
71     for (unsigned int i=0; i < mLightParamsList.size(); ++i)
72     {
73         const LightParams& curParams = mLightParamsList[i];
74 
75         if (curLightType != curParams.mType)
76         {
77             curLightType = curParams.mType;
78             curSearchLightIndex = 0;
79         }
80 
81         Light*      srcLight = NULL;
82         Vector4     vParameter;
83         ColourValue colour;
84 
85         // Search a matching light from the current sorted lights of the given renderable.
86         for (unsigned int j = curSearchLightIndex; j < pLightList->size(); ++j)
87         {
88             if (pLightList->at(j)->getType() == curLightType)
89             {
90                 srcLight = pLightList->at(j);
91                 curSearchLightIndex = j + 1;
92                 break;
93             }
94         }
95 
96         // No matching light found -> use a blank dummy light for parameter update.
97         if (srcLight == NULL)
98         {
99             srcLight = &msBlankLight;
100         }
101 
102 
103         switch (curParams.mType)
104         {
105         case Light::LT_DIRECTIONAL:
106 
107             // Update light direction.
108             vParameter = matWorld * srcLight->getAs4DVector(true);
109             curParams.mDirection->setGpuParameter(vParameter.ptr(),3,1);
110             break;
111 
112         case Light::LT_POINT:
113 
114             // Update light position.
115             vParameter = matWorld * srcLight->getAs4DVector(true);
116             curParams.mPosition->setGpuParameter(vParameter.ptr(),3,1);
117 
118             // Update light attenuation parameters.
119             curParams.mSpotParams->setGpuParameter(Ogre::Vector3(1 / srcLight->getAttenuationRange(),0,0));
120             break;
121 
122         case Light::LT_SPOTLIGHT:
123             {
124                 Ogre::Vector3 vec3;
125 
126                 // Update light position.
127                 vParameter = matWorld * srcLight->getAs4DVector(true);
128                 curParams.mPosition->setGpuParameter(vParameter.ptr(),3,1);
129 
130 
131                 // Update light direction.
132                 vec3 = source->getInverseTransposeWorldMatrix().linear() * srcLight->getDerivedDirection();
133                 vec3.normalise();
134 
135                 vParameter.x = -vec3.x;
136                 vParameter.y = -vec3.y;
137                 vParameter.z = -vec3.z;
138                 vParameter.w = 0.0;
139                 curParams.mDirection->setGpuParameter(vParameter.ptr(),3,1);
140 
141                 // Update spotlight parameters.
142                 Real phi   = Math::Cos(srcLight->getSpotlightOuterAngle().valueRadians() * 0.5f);
143                 Real theta = Math::Cos(srcLight->getSpotlightInnerAngle().valueRadians() * 0.5f);
144 
145                 vec3.x = 1 / srcLight->getAttenuationRange();
146                 vec3.y = phi;
147                 vec3.z = 1 / (theta - phi);
148 
149                 curParams.mSpotParams->setGpuParameter(vec3);
150             }
151             break;
152         }
153 
154         float lightIntensity = 1;
155         if (curParams.mType == Light::LT_SPOTLIGHT)
156         {
157             lightIntensity = spotIntensity;
158         }
159 
160         // Update diffuse colour.
161         colour = srcLight->getDiffuseColour() * lightIntensity;
162         if ((mTrackVertexColourType & TVC_DIFFUSE) == 0)
163         {
164             colour = colour * pass->getDiffuse();
165         }
166         curParams.mDiffuseColour->setGpuParameter(colour.ptr(),3,1);
167 
168         // Update specular colour if need to.
169         if  ((mSpecularEnable) && (curParams.mType == Light::LT_DIRECTIONAL))
170         {
171             // Update diffuse colour.
172             colour = srcLight->getSpecularColour() * lightIntensity;
173             if ((mTrackVertexColourType & TVC_SPECULAR) == 0)
174             {
175                 colour = colour * pass->getSpecular();
176             }
177             curParams.mSpecularColour->setGpuParameter(colour.ptr(),3,1);
178         }
179     }
180 
181     if (mUseSegmentedLightTexture)
182     {
183         unsigned int indexStart = 0, indexEnd = 0;
184         Ogre::Vector4 lightBounds;
185         SegmentedDynamicLightManager::getSingleton().getLightListRange(rend, lightBounds, indexStart, indexEnd);
186         mPSLightTextureIndexLimit->setGpuParameter(Ogre::Vector2((Ogre::Real)indexStart, (Ogre::Real)indexEnd));
187         mPSLightTextureLightBounds->setGpuParameter(lightBounds);
188 
189         Ogre::TextureUnitState* pLightTexture = pass->getTextureUnitState(mLightSamplerIndex);
190         const Ogre::String& textureName = SegmentedDynamicLightManager::getSingleton().getSDLTextureName();
191         if (textureName != pLightTexture->getTextureName())
192         {
193             pLightTexture->setTextureName(textureName, Ogre::TEX_TYPE_2D);
194         }
195     }
196 }
197 
198 //-----------------------------------------------------------------------
resolveParameters(ProgramSet * programSet)199 bool RTShaderSRSSegmentedLights::resolveParameters(ProgramSet* programSet)
200 {
201     if (false == resolveGlobalParameters(programSet))
202         return false;
203 
204     if (false == resolvePerLightParameters(programSet))
205         return false;
206 
207     return true;
208 }
209 
210 //-----------------------------------------------------------------------
resolveGlobalParameters(ProgramSet * programSet)211 bool RTShaderSRSSegmentedLights::resolveGlobalParameters(ProgramSet* programSet)
212 {
213     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
214     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
215     Function* vsMain = vsProgram->getEntryPointFunction();
216     Function* psMain = psProgram->getEntryPointFunction();
217 
218 
219     // Resolve world IT matrix.
220     mWorldITMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLD_MATRIX);
221     if (mWorldITMatrix.get() == NULL)
222         return false;
223 
224     // Get surface ambient colour if need to.
225     if ((mTrackVertexColourType & TVC_AMBIENT) == 0)
226     {
227         mDerivedAmbientLightColour = psProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR);
228         if (mDerivedAmbientLightColour.get() == NULL)
229             return false;
230     }
231     else
232     {
233         mLightAmbientColour = psProgram->resolveParameter(GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
234         if (mLightAmbientColour.get() == NULL)
235             return false;
236 
237         mSurfaceAmbientColour = psProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
238         if (mSurfaceAmbientColour.get() == NULL)
239             return false;
240 
241     }
242 
243     // Get surface diffuse colour if need to.
244     if ((mTrackVertexColourType & TVC_DIFFUSE) == 0)
245     {
246         mSurfaceDiffuseColour = psProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
247         if (mSurfaceDiffuseColour.get() == NULL)
248             return false;
249     }
250 
251     // Get surface specular colour if need to.
252     if ((mTrackVertexColourType & TVC_SPECULAR) == 0)
253     {
254         mSurfaceSpecularColour = psProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_SPECULAR_COLOUR);
255         if (mSurfaceSpecularColour.get() == NULL)
256             return false;
257     }
258 
259 
260     // Get surface emissive colour if need to.
261     if ((mTrackVertexColourType & TVC_EMISSIVE) == 0)
262     {
263         mSurfaceEmissiveColour = psProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
264         if (mSurfaceEmissiveColour.get() == NULL)
265             return false;
266     }
267 
268     // Get derived scene colour.
269     mDerivedSceneColour = psProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_SCENE_COLOUR);
270     if (mDerivedSceneColour.get() == NULL)
271         return false;
272 
273     // Get surface shininess.
274     mSurfaceShininess = psProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_SHININESS);
275     if (mSurfaceShininess.get() == NULL)
276         return false;
277 
278 
279     //Check if another SRS already defined a normal in world space to be used
280     mPSLocalNormal = psMain->getLocalParameter(Parameter::SPC_NORMAL_WORLD_SPACE);
281     if (mPSLocalNormal.get() == NULL)
282     {
283         //create parameters to fetch the normal from the vertex shader
284 
285         // Resolve input vertex shader normal.
286         mVSInNormal = vsMain->resolveInputParameter(Parameter::SPC_NORMAL_OBJECT_SPACE);
287         if (mVSInNormal.get() == NULL)
288             return false;
289 
290         // Resolve output vertex shader normal.
291         mVSOutNormal = vsMain->resolveOutputParameter(Parameter::SPC_NORMAL_WORLD_SPACE);
292         if (mVSOutNormal.get() == NULL)
293             return false;
294 
295         // Resolve input pixel shader normal.
296         mPSInNormal = psMain->resolveInputParameter(mVSOutNormal);
297 
298         if (mPSInNormal.get() == NULL)
299             return false;
300 
301         mPSLocalNormal = psMain->resolveLocalParameter(Parameter::SPC_NORMAL_WORLD_SPACE);
302     }
303 
304     mPSDiffuse = psMain->getInputParameter(Parameter::SPC_COLOR_DIFFUSE);
305     if (mPSDiffuse.get() == NULL)
306     {
307         mPSDiffuse = psMain->getLocalParameter(Parameter::SPC_COLOR_DIFFUSE);
308         if (mPSDiffuse.get() == NULL)
309             return false;
310     }
311 
312     mPSOutDiffuse = psMain->resolveOutputParameter(Parameter::SPS_COLOR, 0, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
313     if (mPSOutDiffuse.get() == NULL)
314         return false;
315 
316     mPSTempDiffuseColour = psMain->resolveLocalParameter("lPerPixelDiffuse", GCT_FLOAT4);
317     if (mPSTempDiffuseColour.get() == NULL)
318         return false;
319 
320     mVSOutWorldPos = vsMain->resolveOutputParameter(Parameter::SPC_POSITION_WORLD_SPACE);
321     if (mVSOutWorldPos.get() == NULL)
322         return false;
323 
324     mPSInWorldPos = psMain->resolveInputParameter(mVSOutWorldPos);
325     if (mPSInWorldPos.get() == NULL)
326         return false;
327 
328     mWorldMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_MATRIX);
329     if (mWorldMatrix.get() == NULL)
330         return false;
331 
332     mVSInPosition = vsMain->resolveInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE);
333     if (mVSInPosition.get() == NULL)
334         return false;
335 
336     if (mSpecularEnable)
337     {
338         mPSSpecular = psMain->getInputParameter(Parameter::SPC_COLOR_SPECULAR);
339         if (mPSSpecular.get() == NULL)
340         {
341             mPSSpecular = psMain->getLocalParameter(Parameter::SPC_COLOR_SPECULAR);
342             if (mPSSpecular.get() == NULL)
343                 return false;
344         }
345 
346         mPSTempSpecularColour = psMain->resolveLocalParameter("lPerPixelSpecular", GCT_FLOAT4);
347         if (mPSTempSpecularColour.get() == NULL)
348             return false;
349 
350 
351         mVSInPosition = vsMain->resolveInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE);
352         if (mVSInPosition.get() == NULL)
353             return false;
354 
355         mWorldMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_MATRIX);
356         if (mWorldMatrix.get() == NULL)
357             return false;
358     }
359 
360 
361     if (mUseSegmentedLightTexture)
362     {
363         mPSLightTextureIndexLimit = psProgram->resolveParameter(GCT_FLOAT2, -1, (uint16)GPV_PER_OBJECT, "LightTextureIndexLimits");
364         mPSLightTextureLightBounds = psProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_PER_OBJECT, "LightTextureBounds");
365         mPSSegmentedLightTexture = psProgram->resolveParameter(Ogre::GCT_SAMPLER2D, mLightSamplerIndex, (Ogre::uint16)Ogre::GPV_GLOBAL, "segmentedLightTexture");
366     }
367 
368     return true;
369 }
370 
371 //-----------------------------------------------------------------------
resolvePerLightParameters(ProgramSet * programSet)372 bool RTShaderSRSSegmentedLights::resolvePerLightParameters(ProgramSet* programSet)
373 {
374     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
375 
376     // Resolve per light parameters.
377     for (unsigned int i=0; i < mLightParamsList.size(); ++i)
378     {
379         switch (mLightParamsList[i].mType)
380         {
381         case Light::LT_DIRECTIONAL:
382             mLightParamsList[i].mDirection = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS, "light_direction_space");
383             if (mLightParamsList[i].mDirection.get() == NULL)
384                 return false;
385             break;
386 
387         case Light::LT_POINT:
388         case Light::LT_SPOTLIGHT:
389             mLightParamsList[i].mPosition = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS, "light_position_space");
390             if (mLightParamsList[i].mPosition.get() == NULL)
391                 return false;
392 
393             mLightParamsList[i].mDirection = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS, "light_direction_space");
394             if (mLightParamsList[i].mDirection.get() == NULL)
395                 return false;
396 
397             mLightParamsList[i].mSpotParams = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS, "spotlight_params");
398             if (mLightParamsList[i].mSpotParams.get() == NULL)
399                 return false;
400 
401             break;
402         }
403 
404         // Resolve diffuse colour.
405         if ((mTrackVertexColourType & TVC_DIFFUSE) == 0)
406         {
407             mLightParamsList[i].mDiffuseColour = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS | (uint16)GPV_GLOBAL, "derived_light_diffuse");
408             if (mLightParamsList[i].mDiffuseColour.get() == NULL)
409                 return false;
410         }
411         else
412         {
413             mLightParamsList[i].mDiffuseColour = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS, "light_diffuse");
414             if (mLightParamsList[i].mDiffuseColour.get() == NULL)
415                 return false;
416         }
417 
418         if ((mSpecularEnable) && (mLightParamsList[i].mType == Light::LT_DIRECTIONAL))
419         {
420             // Resolve specular colour.
421             if ((mTrackVertexColourType & TVC_SPECULAR) == 0)
422             {
423                 mLightParamsList[i].mSpecularColour = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS | (uint16)GPV_GLOBAL, "derived_light_specular");
424                 if (mLightParamsList[i].mSpecularColour.get() == NULL)
425                     return false;
426             }
427             else
428             {
429                 mLightParamsList[i].mSpecularColour = psProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS, "light_specular");
430                 if (mLightParamsList[i].mSpecularColour.get() == NULL)
431                     return false;
432             }
433         }
434 
435     }
436 
437     return true;
438 }
439 
440 //-----------------------------------------------------------------------
resolveDependencies(ProgramSet * programSet)441 bool RTShaderSRSSegmentedLights::resolveDependencies(ProgramSet* programSet)
442 {
443     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
444     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
445 
446     vsProgram->addDependency(FFP_LIB_COMMON);
447     vsProgram->addDependency(SL_LIB_PERPIXELLIGHTING);
448 
449     psProgram->addDependency(FFP_LIB_COMMON);
450     psProgram->addDependency(SL_LIB_PERPIXELLIGHTING);
451 
452     return true;
453 }
454 
455 //-----------------------------------------------------------------------
addFunctionInvocations(ProgramSet * programSet)456 bool RTShaderSRSSegmentedLights::addFunctionInvocations(ProgramSet* programSet)
457 {
458     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
459     Function* vsMain = vsProgram->getEntryPointFunction();
460     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
461     Function* psMain = psProgram->getEntryPointFunction();
462 
463     // Add the global illumination functions.
464     if (false == addVSInvocation(vsMain, FFP_VS_LIGHTING))
465         return false;
466 
467     // Add the global illumination functions.
468     if (false == addPSGlobalIlluminationInvocationBegin(psMain, FFP_PS_COLOUR_BEGIN + 1))
469         return false;
470 
471 
472     // Add per light functions.
473     for (unsigned int i=0; i < mLightParamsList.size(); ++i)
474     {
475         if (false == addPSIlluminationInvocation(&mLightParamsList[i], psMain, FFP_PS_COLOUR_BEGIN + 1))
476             return false;
477     }
478 
479     if (mUseSegmentedLightTexture)
480     {
481         addPSSegmentedTextureLightInvocation(psMain, FFP_PS_COLOUR_BEGIN + 1);
482     }
483 
484 
485     // Add the global illumination functions.
486     if (false == addPSGlobalIlluminationInvocationEnd(psMain, FFP_PS_COLOUR_BEGIN + 1))
487         return false;
488 
489 
490     // Assign back temporary variables to the ps diffuse and specular components.
491     if (false == addPSFinalAssignmentInvocation(psMain, FFP_PS_COLOUR_BEGIN + 1))
492         return false;
493 
494 
495     return true;
496 }
497 
498 //-----------------------------------------------------------------------
addVSInvocation(Function * vsMain,const int groupOrder)499 bool RTShaderSRSSegmentedLights::addVSInvocation(Function* vsMain, const int groupOrder)
500 {
501     FunctionInvocation* curFuncInvocation = NULL;
502 
503     if (mVSInNormal.get() != NULL)
504     {
505         // Transform normal in world space.
506         curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_TRANSFORMNORMAL, groupOrder);
507         curFuncInvocation->pushOperand(mWorldITMatrix, Operand::OPS_IN);
508         curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
509         curFuncInvocation->pushOperand(mVSOutNormal, Operand::OPS_OUT);
510         vsMain->addAtomInstance(curFuncInvocation);
511     }
512 
513     // Transform world space position if need to.
514     if (mVSOutWorldPos.get() != NULL)
515     {
516         curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_TRANSFORMPOSITION, groupOrder);
517         curFuncInvocation->pushOperand(mWorldMatrix, Operand::OPS_IN);
518         curFuncInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
519         curFuncInvocation->pushOperand(mVSOutWorldPos, Operand::OPS_OUT);
520         vsMain->addAtomInstance(curFuncInvocation);
521     }
522 
523 
524     return true;
525 }
526 
527 
528 //-----------------------------------------------------------------------
addPSGlobalIlluminationInvocationBegin(Function * psMain,const int groupOrder)529 bool RTShaderSRSSegmentedLights::addPSGlobalIlluminationInvocationBegin(Function* psMain, const int groupOrder)
530 {
531     FunctionInvocation* curFuncInvocation = NULL;
532 
533     if (mPSInNormal.get())
534     {
535         curFuncInvocation = OGRE_NEW AssignmentAtom(FFP_PS_PRE_PROCESS + 1);
536         curFuncInvocation->pushOperand(mPSInNormal, Operand::OPS_IN);
537         curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_OUT);
538         psMain->addAtomInstance(curFuncInvocation);
539     }
540 
541     //alpha channel is controlled by the diffuse value
542     if (mTrackVertexColourType & TVC_DIFFUSE)
543     {
544         curFuncInvocation = OGRE_NEW AssignmentAtom(groupOrder);
545         curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_W);
546         curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_W);
547         psMain->addAtomInstance(curFuncInvocation);
548     }
549     else
550     {
551         curFuncInvocation = OGRE_NEW AssignmentAtom(groupOrder);
552         curFuncInvocation->pushOperand(mDerivedSceneColour, Operand::OPS_IN, Operand::OPM_W);
553         curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_W);
554         psMain->addAtomInstance(curFuncInvocation);
555     }
556 
557     ParameterPtr pZeroParam = ParameterFactory::createConstParam(Ogre::Vector3::ZERO);
558 
559     curFuncInvocation = OGRE_NEW AssignmentAtom(groupOrder);
560     curFuncInvocation->pushOperand(pZeroParam, Operand::OPS_IN);
561     curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
562     psMain->addAtomInstance(curFuncInvocation);
563 
564     if (mSpecularEnable)
565     {
566         curFuncInvocation = OGRE_NEW AssignmentAtom(groupOrder);
567         curFuncInvocation->pushOperand(pZeroParam, Operand::OPS_IN);
568         curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_OUT, Operand::OPM_XYZ);
569         psMain->addAtomInstance(curFuncInvocation);
570     }
571 
572     return true;
573 }
574 
575 
576 
577 //-----------------------------------------------------------------------
addPSGlobalIlluminationInvocationEnd(Function * psMain,const int groupOrder)578 bool RTShaderSRSSegmentedLights::addPSGlobalIlluminationInvocationEnd(Function* psMain, const int groupOrder)
579 {
580     FunctionInvocation* curFuncInvocation = NULL;
581 
582     // Merge diffuse colour with vertex colour if need to.
583     if (mTrackVertexColourType & TVC_DIFFUSE)
584     {
585         curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder);
586         curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
587         curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
588         curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
589         psMain->addAtomInstance(curFuncInvocation);
590     }
591 
592     // Merge specular colour with vertex colour if need to.
593     if ((mSpecularEnable == true) && (mTrackVertexColourType & TVC_SPECULAR))
594     {
595         curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder);
596         curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
597         curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
598         curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_OUT, Operand::OPM_XYZ);
599         psMain->addAtomInstance(curFuncInvocation);
600     }
601 
602 
603     if ((mTrackVertexColourType & TVC_AMBIENT) == 0 &&
604         (mTrackVertexColourType & TVC_EMISSIVE) == 0)
605     {
606         curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder);
607         curFuncInvocation->pushOperand(mDerivedSceneColour, Operand::OPS_IN, (Operand::OPM_XYZ));
608         curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, (Operand::OPM_XYZ));
609         curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
610         psMain->addAtomInstance(curFuncInvocation);
611     }
612     else
613     {
614         if (mTrackVertexColourType & TVC_AMBIENT)
615         {
616             curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder);
617             curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
618             curFuncInvocation->pushOperand(mLightAmbientColour, Operand::OPS_IN, Operand::OPM_XYZ);
619             curFuncInvocation->pushOperand(mLightAmbientColour, Operand::OPS_OUT, Operand::OPM_XYZ);
620             psMain->addAtomInstance(curFuncInvocation);
621 
622             curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder);
623             curFuncInvocation->pushOperand(mLightAmbientColour, Operand::OPS_IN, Operand::OPM_XYZ);
624             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
625             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
626             psMain->addAtomInstance(curFuncInvocation);
627         }
628         else
629         {
630             curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder);
631             curFuncInvocation->pushOperand(mDerivedAmbientLightColour, Operand::OPS_IN, Operand::OPM_XYZ);
632             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
633             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
634             psMain->addAtomInstance(curFuncInvocation);
635         }
636 
637         if (mTrackVertexColourType & TVC_EMISSIVE)
638         {
639             curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder);
640             curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
641             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
642             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
643             psMain->addAtomInstance(curFuncInvocation);
644         }
645         else
646         {
647             curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder);
648             curFuncInvocation->pushOperand(mSurfaceEmissiveColour, Operand::OPS_IN, Operand::OPM_XYZ);
649             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
650             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
651             psMain->addAtomInstance(curFuncInvocation);
652         }
653     }
654 
655     if (mSpecularEnable)
656     {
657         curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder);
658         curFuncInvocation->pushOperand(mPSSpecular, Operand::OPS_IN);
659         curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN);
660         curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_OUT);
661         psMain->addAtomInstance(curFuncInvocation);
662     }
663 
664     return true;
665 }
666 
667 //-----------------------------------------------------------------------
addPSIlluminationInvocation(LightParams * curLightParams,Function * psMain,const int groupOrder)668 bool RTShaderSRSSegmentedLights::addPSIlluminationInvocation(LightParams* curLightParams, Function* psMain, const int groupOrder)
669 {
670     FunctionInvocation* curFuncInvocation = NULL;
671 
672 
673     switch (curLightParams->mType)
674     {
675 
676     case Light::LT_DIRECTIONAL:
677         if (mSpecularEnable)
678         {
679             curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_DIRECTIONAL_DIFFUSESPECULAR, groupOrder);
680             curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
681             curFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);
682             curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN);
683             curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN);
684             curFuncInvocation->pushOperand(curLightParams->mSpecularColour, Operand::OPS_IN);
685             curFuncInvocation->pushOperand(mSurfaceShininess, Operand::OPS_IN);
686             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
687             curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
688             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
689             curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_OUT, Operand::OPM_XYZ);
690             psMain->addAtomInstance(curFuncInvocation);
691         }
692 
693         else
694         {
695             curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_DIRECTIONAL_DIFFUSE, groupOrder);
696             curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
697             curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN);
698             curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN);
699             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
700             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
701             psMain->addAtomInstance(curFuncInvocation);
702         }
703         break;
704 
705     case Light::LT_POINT:
706     case Light::LT_SPOTLIGHT:
707         {
708             curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_AMBIENT_DIFFUSE, groupOrder);
709             curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
710             curFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);
711             curFuncInvocation->pushOperand(curLightParams->mPosition, Operand::OPS_IN);
712             curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN);
713             curFuncInvocation->pushOperand(curLightParams->mSpotParams, Operand::OPS_IN);
714             curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN);
715             curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_INOUT, Operand::OPM_XYZ);
716             psMain->addAtomInstance(curFuncInvocation);
717         }
718         break;
719     }
720 
721     return true;
722 }
723 
addPSSegmentedTextureLightInvocation(Function * psMain,const int groupOrder)724 bool RTShaderSRSSegmentedLights::addPSSegmentedTextureLightInvocation(Function* psMain, const int groupOrder)
725 {
726     float invWidth = 1.0f / (float)SegmentedDynamicLightManager::getSingleton().getTextureWidth();
727     float invHeight = 1.0f / (float)SegmentedDynamicLightManager::getSingleton().getTextureHeight();
728     ParameterPtr paramInvWidth = ParameterFactory::createConstParam(invWidth);
729     ParameterPtr paramInvHeight = ParameterFactory::createConstParam(invHeight);
730 
731     FunctionInvocation* curFuncInvocation = NULL;
732     curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_SEGMENT_TEXTURE_AMBIENT_DIFFUSE, groupOrder);
733     curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
734     curFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);
735     curFuncInvocation->pushOperand(mPSSegmentedLightTexture, Operand::OPS_IN);
736     curFuncInvocation->pushOperand(mPSLightTextureIndexLimit, Operand::OPS_IN);
737     curFuncInvocation->pushOperand(mPSLightTextureLightBounds, Operand::OPS_IN);
738     curFuncInvocation->pushOperand(paramInvWidth, Operand::OPS_IN);
739     curFuncInvocation->pushOperand(paramInvHeight, Operand::OPS_IN);
740     curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_INOUT, Operand::OPM_XYZ);
741     psMain->addAtomInstance(curFuncInvocation);
742 
743     if (SegmentedDynamicLightManager::getSingleton().isDebugMode())
744     {
745         ParameterPtr psOutColor = psMain->resolveOutputParameter(Parameter::SPS_COLOR, -1, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
746 
747         FunctionInvocation* curDebugFuncInvocation = NULL;
748         curDebugFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_SEGMENT_DEBUG, FFP_PS_COLOUR_END + 1);
749         curDebugFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
750         curDebugFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);
751         curDebugFuncInvocation->pushOperand(mPSSegmentedLightTexture, Operand::OPS_IN);
752         curDebugFuncInvocation->pushOperand(mPSLightTextureIndexLimit, Operand::OPS_IN);
753         curDebugFuncInvocation->pushOperand(mPSLightTextureLightBounds, Operand::OPS_IN);
754         curDebugFuncInvocation->pushOperand(paramInvWidth, Operand::OPS_IN);
755         curDebugFuncInvocation->pushOperand(paramInvHeight, Operand::OPS_IN);
756 
757         curDebugFuncInvocation->pushOperand(psOutColor, Operand::OPS_INOUT, Operand::OPM_XYZ);
758         psMain->addAtomInstance(curDebugFuncInvocation);
759     }
760 
761     return true;
762 }
763 
764 
765 //-----------------------------------------------------------------------
addPSFinalAssignmentInvocation(Function * psMain,const int groupOrder)766 bool RTShaderSRSSegmentedLights::addPSFinalAssignmentInvocation( Function* psMain, const int groupOrder)
767 {
768     FunctionInvocation* curFuncInvocation;
769 
770     curFuncInvocation = OGRE_NEW AssignmentAtom(FFP_PS_COLOUR_BEGIN + 1);
771     curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN);
772     curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_OUT);
773     psMain->addAtomInstance(curFuncInvocation);
774 
775     curFuncInvocation = OGRE_NEW AssignmentAtom(FFP_PS_COLOUR_BEGIN + 1);
776     curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN);
777     curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT);
778     psMain->addAtomInstance(curFuncInvocation);
779 
780     if (mSpecularEnable)
781     {
782         curFuncInvocation = OGRE_NEW AssignmentAtom(FFP_PS_COLOUR_BEGIN + 1);
783         curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN);
784         curFuncInvocation->pushOperand(mPSSpecular, Operand::OPS_OUT);
785         psMain->addAtomInstance(curFuncInvocation);
786     }
787 
788     return true;
789 }
790 
791 
792 //-----------------------------------------------------------------------
copyFrom(const SubRenderState & rhs)793 void RTShaderSRSSegmentedLights::copyFrom(const SubRenderState& rhs)
794 {
795     const RTShaderSRSSegmentedLights& rhsLighting = static_cast<const RTShaderSRSSegmentedLights&>(rhs);
796 
797     mUseSegmentedLightTexture = rhsLighting.mUseSegmentedLightTexture;
798 
799     int lightCount[3];
800 
801     rhsLighting.getLightCount(lightCount);
802     setLightCount(lightCount);
803 }
804 
805 //-----------------------------------------------------------------------
preAddToRenderState(const RenderState * renderState,Pass * srcPass,Pass * dstPass)806 bool RTShaderSRSSegmentedLights::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass)
807 {
808     if (srcPass->getLightingEnabled() == false)
809         return false;
810 
811     mUseSegmentedLightTexture = SegmentedDynamicLightManager::getSingleton().isActive();
812     setTrackVertexColourType(srcPass->getVertexColourTracking());
813 
814     if (srcPass->getShininess() > 0.0 &&
815         srcPass->getSpecular() != ColourValue::Black)
816     {
817         setSpecularEnable(true);
818     }
819     else
820     {
821         setSpecularEnable(false);
822     }
823 
824 
825     int lightCount[3];
826     renderState->getLightCount(lightCount);
827     setLightCount(lightCount);
828 
829     if (mUseSegmentedLightTexture)
830     {
831         const_cast<RenderState*>(renderState)->setLightCountAutoUpdate(false);
832 
833         Ogre::TextureUnitState* pLightTexture = dstPass->createTextureUnitState();
834         pLightTexture->setTextureName(SegmentedDynamicLightManager::getSingleton().getSDLTextureName(), Ogre::TEX_TYPE_2D);
835         pLightTexture->setTextureFiltering(Ogre::TFO_NONE);
836         mLightSamplerIndex = dstPass->getNumTextureUnitStates() - 1;
837     }
838 
839 
840     return true;
841 }
842 
843 //-----------------------------------------------------------------------
setLightCount(const int lightCount[3])844 void RTShaderSRSSegmentedLights::setLightCount(const int lightCount[3])
845 {
846     mLightParamsList.clear();
847     //Set always to have one single directional lights
848     LightParams curParams;
849     curParams.mType = Light::LT_DIRECTIONAL;
850     mLightParamsList.push_back(curParams);
851 
852     for (int type=0; type < 3; ++type)
853     {
854         for (int i=0; i < lightCount[type]; ++i)
855         {
856 
857             if (type == 0)
858                 curParams.mType = Light::LT_POINT;
859             //else if (type == 1)
860             //  curParams.mType = Light::LT_DIRECTIONAL;
861             else if (type == 2)
862                 curParams.mType = Light::LT_SPOTLIGHT;
863 
864             if ((!mUseSegmentedLightTexture) || (curParams.mType == Light::LT_DIRECTIONAL))
865             {
866                 mLightParamsList.push_back(curParams);
867             }
868         }
869     }
870 }
871 
872 //-----------------------------------------------------------------------
getLightCount(int lightCount[3]) const873 void RTShaderSRSSegmentedLights::getLightCount(int lightCount[3]) const
874 {
875     lightCount[0] = 0;
876     lightCount[1] = 0;
877     lightCount[2] = 0;
878 
879     for (unsigned int i=0; i < mLightParamsList.size(); ++i)
880     {
881         const LightParams curParams = mLightParamsList[i];
882 
883         if (curParams.mType == Light::LT_POINT)
884             lightCount[0]++;
885         else if (curParams.mType == Light::LT_DIRECTIONAL)
886             lightCount[1]++;
887         else if (curParams.mType == Light::LT_SPOTLIGHT)
888             lightCount[2]++;
889     }
890 }
891 
892 
893 //-----------------------------------------------------------------------
getType() const894 const String& RTShaderSRSSegmentedLightsFactory::getType() const
895 {
896     return RTShaderSRSSegmentedLights::Type;
897 }
898 
899 //-----------------------------------------------------------------------
createInstance(ScriptCompiler * compiler,PropertyAbstractNode * prop,Pass * pass,SGScriptTranslator * translator)900 SubRenderState* RTShaderSRSSegmentedLightsFactory::createInstance(ScriptCompiler* compiler,
901         PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator)
902 {
903     if (prop->name == "lighting_stage")
904     {
905         if(prop->values.size() == 1)
906         {
907             String modelType;
908 
909             if(false == SGScriptTranslator::getString(prop->values.front(), &modelType))
910             {
911                 compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
912                 return NULL;
913             }
914 
915             if (modelType == "per_pixel")
916             {
917                 return createOrRetrieveInstance(translator);
918             }
919         }
920     }
921 
922     return NULL;
923 }
924 
925 //-----------------------------------------------------------------------
writeInstance(MaterialSerializer * ser,SubRenderState * subRenderState,Pass * srcPass,Pass * dstPass)926 void RTShaderSRSSegmentedLightsFactory::writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState,
927     Pass* srcPass, Pass* dstPass)
928 {
929     ser->writeAttribute(4, "lighting_stage");
930     ser->writeValue("per_pixel");
931 }
932 
933 //-----------------------------------------------------------------------
createInstanceImpl()934 SubRenderState* RTShaderSRSSegmentedLightsFactory::createInstanceImpl()
935 {
936     return OGRE_NEW RTShaderSRSSegmentedLights;
937 }
938 
939