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