1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org
6
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 -----------------------------------------------------------------------------
26 */
27 #include "OgreShaderFFPLighting.h"
28 #ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
29 #include "OgreShaderFFPRenderState.h"
30 #include "OgreShaderProgram.h"
31 #include "OgreShaderParameter.h"
32 #include "OgreShaderProgramSet.h"
33 #include "OgreGpuProgram.h"
34 #include "OgrePass.h"
35 #include "OgreShaderGenerator.h"
36 #include "OgreSceneManager.h"
37 #include "OgreViewport.h"
38
39
40 namespace Ogre {
41 namespace RTShader {
42
43 /************************************************************************/
44 /* */
45 /************************************************************************/
46 String FFPLighting::Type = "FFP_Lighting";
47 Light FFPLighting::msBlankLight;
48
49 //-----------------------------------------------------------------------
FFPLighting()50 FFPLighting::FFPLighting()
51 {
52 mTrackVertexColourType = TVC_NONE;
53 mSpecularEnable = false;
54
55 msBlankLight.setDiffuseColour(ColourValue::Black);
56 msBlankLight.setSpecularColour(ColourValue::Black);
57 msBlankLight.setAttenuation(0,1,0,0);
58 }
59
60 //-----------------------------------------------------------------------
getType() const61 const String& FFPLighting::getType() const
62 {
63 return Type;
64 }
65
66
67 //-----------------------------------------------------------------------
getExecutionOrder() const68 int FFPLighting::getExecutionOrder() const
69 {
70 return FFP_LIGHTING;
71 }
72
73 //-----------------------------------------------------------------------
updateGpuProgramsParams(Renderable * rend,Pass * pass,const AutoParamDataSource * source,const LightList * pLightList)74 void FFPLighting::updateGpuProgramsParams(Renderable* rend, Pass* pass, const AutoParamDataSource* source,
75 const LightList* pLightList)
76 {
77 if (mLightParamsList.empty())
78 return;
79
80 const Matrix4& matView = source->getViewMatrix();
81 Light::LightTypes curLightType = Light::LT_DIRECTIONAL;
82 unsigned int curSearchLightIndex = 0;
83
84 // Update per light parameters.
85 for (unsigned int i=0; i < mLightParamsList.size(); ++i)
86 {
87 const LightParams& curParams = mLightParamsList[i];
88
89 if (curLightType != curParams.mType)
90 {
91 curLightType = curParams.mType;
92 curSearchLightIndex = 0;
93 }
94
95 Light* srcLight = NULL;
96 Vector4 vParameter;
97 ColourValue colour;
98
99 // Search a matching light from the current sorted lights of the given renderable.
100 for (unsigned int j = curSearchLightIndex; j < pLightList->size(); ++j)
101 {
102 if (pLightList->at(j)->getType() == curLightType)
103 {
104 srcLight = pLightList->at(j);
105 curSearchLightIndex = j + 1;
106 break;
107 }
108 }
109
110 // No matching light found -> use a blank dummy light for parameter update.
111 if (srcLight == NULL)
112 {
113 srcLight = &msBlankLight;
114 }
115
116
117 switch (curParams.mType)
118 {
119 case Light::LT_DIRECTIONAL:
120
121 // Update light direction.
122 vParameter = matView.transformAffine(srcLight->getAs4DVector(true));
123 curParams.mDirection->setGpuParameter(vParameter);
124 break;
125
126 case Light::LT_POINT:
127
128 // Update light position.
129 vParameter = matView.transformAffine(srcLight->getAs4DVector(true));
130 curParams.mPosition->setGpuParameter(vParameter);
131
132 // Update light attenuation parameters.
133 vParameter.x = srcLight->getAttenuationRange();
134 vParameter.y = srcLight->getAttenuationConstant();
135 vParameter.z = srcLight->getAttenuationLinear();
136 vParameter.w = srcLight->getAttenuationQuadric();
137 curParams.mAttenuatParams->setGpuParameter(vParameter);
138 break;
139
140 case Light::LT_SPOTLIGHT:
141 {
142 Vector3 vec3;
143 Matrix3 matViewIT;
144
145 source->getInverseTransposeViewMatrix().extract3x3Matrix(matViewIT);
146
147
148 // Update light position.
149 vParameter = matView.transformAffine(srcLight->getAs4DVector(true));
150 curParams.mPosition->setGpuParameter(vParameter);
151
152
153 vec3 = matViewIT * srcLight->getDerivedDirection();
154 vec3.normalise();
155
156 vParameter.x = -vec3.x;
157 vParameter.y = -vec3.y;
158 vParameter.z = -vec3.z;
159 vParameter.w = 0.0;
160 curParams.mDirection->setGpuParameter(vParameter);
161
162 // Update light attenuation parameters.
163 vParameter.x = srcLight->getAttenuationRange();
164 vParameter.y = srcLight->getAttenuationConstant();
165 vParameter.z = srcLight->getAttenuationLinear();
166 vParameter.w = srcLight->getAttenuationQuadric();
167 curParams.mAttenuatParams->setGpuParameter(vParameter);
168
169 // Update spotlight parameters.
170 Real phi = Math::Cos(srcLight->getSpotlightOuterAngle().valueRadians() * 0.5f);
171 Real theta = Math::Cos(srcLight->getSpotlightInnerAngle().valueRadians() * 0.5f);
172
173 vec3.x = theta;
174 vec3.y = phi;
175 vec3.z = srcLight->getSpotlightFalloff();
176
177 curParams.mSpotParams->setGpuParameter(vec3);
178 }
179 break;
180 }
181
182
183 // Update diffuse colour.
184 if ((mTrackVertexColourType & TVC_DIFFUSE) == 0)
185 {
186 colour = srcLight->getDiffuseColour() * pass->getDiffuse() * srcLight->getPowerScale();
187 curParams.mDiffuseColour->setGpuParameter(colour);
188 }
189 else
190 {
191 colour = srcLight->getDiffuseColour() * srcLight->getPowerScale();
192 curParams.mDiffuseColour->setGpuParameter(colour);
193 }
194
195 // Update specular colour if need to.
196 if (mSpecularEnable)
197 {
198 // Update diffuse colour.
199 if ((mTrackVertexColourType & TVC_SPECULAR) == 0)
200 {
201 colour = srcLight->getSpecularColour() * pass->getSpecular() * srcLight->getPowerScale();
202 curParams.mSpecularColour->setGpuParameter(colour);
203 }
204 else
205 {
206 colour = srcLight->getSpecularColour() * srcLight->getPowerScale();
207 curParams.mSpecularColour->setGpuParameter(colour);
208 }
209 }
210 }
211 }
212
213 //-----------------------------------------------------------------------
resolveParameters(ProgramSet * programSet)214 bool FFPLighting::resolveParameters(ProgramSet* programSet)
215 {
216 Program* vsProgram = programSet->getCpuVertexProgram();
217 Function* vsMain = vsProgram->getEntryPointFunction();
218 bool hasError = false;
219
220 // Resolve world view IT matrix.
221 mWorldViewITMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLDVIEW_MATRIX, 0);
222
223 // Get surface ambient colour if need to.
224 if ((mTrackVertexColourType & TVC_AMBIENT) == 0)
225 {
226 mDerivedAmbientLightColour = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR, 0);
227 hasError |= !(mDerivedAmbientLightColour.get());
228 }
229 else
230 {
231 mLightAmbientColour = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR, 0);
232 mSurfaceAmbientColour = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR, 0);
233
234 hasError |= !(mLightAmbientColour.get()) || !(mSurfaceAmbientColour.get());
235 }
236
237 // Get surface diffuse colour if need to.
238 if ((mTrackVertexColourType & TVC_DIFFUSE) == 0)
239 {
240 mSurfaceDiffuseColour = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR, 0);
241 hasError |= !(mSurfaceDiffuseColour.get());
242 }
243
244 // Get surface specular colour if need to.
245 if ((mTrackVertexColourType & TVC_SPECULAR) == 0)
246 {
247 mSurfaceSpecularColour = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_SURFACE_SPECULAR_COLOUR, 0);
248 hasError |= !(mSurfaceSpecularColour.get());
249 }
250
251
252 // Get surface emissive colour if need to.
253 if ((mTrackVertexColourType & TVC_EMISSIVE) == 0)
254 {
255 mSurfaceEmissiveColour = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR, 0);
256 hasError |= !(mSurfaceEmissiveColour.get());
257 }
258
259 // Get derived scene colour.
260 mDerivedSceneColour = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_DERIVED_SCENE_COLOUR, 0);
261
262 // Get surface shininess.
263 mSurfaceShininess = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_SURFACE_SHININESS, 0);
264
265 // Resolve input vertex shader normal.
266 mVSInNormal = vsMain->resolveInputParameter(Parameter::SPS_NORMAL, 0, Parameter::SPC_NORMAL_OBJECT_SPACE, GCT_FLOAT3);
267
268 if (mTrackVertexColourType != 0)
269 {
270 mVSDiffuse = vsMain->resolveInputParameter(Parameter::SPS_COLOR, 0, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
271 hasError |= !(mVSDiffuse.get());
272 }
273
274
275 // Resolve output vertex shader diffuse colour.
276 mVSOutDiffuse = vsMain->resolveOutputParameter(Parameter::SPS_COLOR, 0, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
277
278 // Resolve per light parameters.
279 for (unsigned int i=0; i < mLightParamsList.size(); ++i)
280 {
281 switch (mLightParamsList[i].mType)
282 {
283 case Light::LT_DIRECTIONAL:
284 mLightParamsList[i].mDirection = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_position_view_space");
285 hasError |= !(mLightParamsList[i].mDirection.get());
286 break;
287
288 case Light::LT_POINT:
289 mWorldViewMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLDVIEW_MATRIX, 0);
290
291 mVSInPosition = vsMain->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4);
292
293 mLightParamsList[i].mPosition = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_position_view_space");
294
295 mLightParamsList[i].mAttenuatParams = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_attenuation");
296
297 hasError |= !(mWorldViewMatrix.get()) || !(mVSInPosition.get()) || !(mLightParamsList[i].mPosition.get()) || !(mLightParamsList[i].mAttenuatParams.get());
298 break;
299
300 case Light::LT_SPOTLIGHT:
301 mWorldViewMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLDVIEW_MATRIX, 0);
302
303 mVSInPosition = vsMain->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4);
304
305 mLightParamsList[i].mPosition = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_position_view_space");
306
307 mLightParamsList[i].mDirection = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_direction_view_space");
308
309 mLightParamsList[i].mAttenuatParams = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_attenuation");
310
311 mLightParamsList[i].mSpotParams = vsProgram->resolveParameter(GCT_FLOAT3, -1, (uint16)GPV_LIGHTS, "spotlight_params");
312
313 hasError |= !(mWorldViewMatrix.get()) || !(mVSInPosition.get()) || !(mLightParamsList[i].mPosition.get()) ||
314 !(mLightParamsList[i].mDirection.get()) || !(mLightParamsList[i].mAttenuatParams.get()) || !(mLightParamsList[i].mSpotParams.get());
315 break;
316 }
317
318 // Resolve diffuse colour.
319 if ((mTrackVertexColourType & TVC_DIFFUSE) == 0)
320 {
321 mLightParamsList[i].mDiffuseColour = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_GLOBAL | (uint16)GPV_LIGHTS, "derived_light_diffuse");
322 hasError |= !(mLightParamsList[i].mDiffuseColour.get());
323 }
324 else
325 {
326 mLightParamsList[i].mDiffuseColour = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_diffuse");
327 hasError |= !(mLightParamsList[i].mDiffuseColour.get());
328 }
329
330 if (mSpecularEnable)
331 {
332 // Resolve specular colour.
333 if ((mTrackVertexColourType & TVC_SPECULAR) == 0)
334 {
335 mLightParamsList[i].mSpecularColour = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_GLOBAL | (uint16)GPV_LIGHTS, "derived_light_specular");
336 hasError |= !(mLightParamsList[i].mSpecularColour.get());
337 }
338 else
339 {
340 mLightParamsList[i].mSpecularColour = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS, "light_specular");
341 hasError |= !(mLightParamsList[i].mSpecularColour.get());
342 }
343
344 if (mVSOutSpecular.get() == NULL)
345 {
346 mVSOutSpecular = vsMain->resolveOutputParameter(Parameter::SPS_COLOR, 1, Parameter::SPC_COLOR_SPECULAR, GCT_FLOAT4);
347 hasError |= !(mVSOutSpecular.get());
348 }
349
350 if (mVSInPosition.get() == NULL)
351 {
352 mVSInPosition = vsMain->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4);
353 hasError |= !(mVSInPosition.get());
354 }
355
356 if (mWorldViewMatrix.get() == NULL)
357 {
358 mWorldViewMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLDVIEW_MATRIX, 0);
359 hasError |= !(mWorldViewMatrix.get());
360 }
361 }
362 }
363
364 hasError |= !(mWorldViewITMatrix.get()) || !(mDerivedSceneColour.get()) || !(mSurfaceShininess.get()) ||
365 !(mVSInNormal.get()) || !(mVSOutDiffuse.get());
366
367
368 if (hasError)
369 {
370 OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
371 "Not all parameters could be constructed for the sub-render state.",
372 "PerPixelLighting::resolveGlobalParameters" );
373 }
374
375 return true;
376 }
377
378 //-----------------------------------------------------------------------
resolveDependencies(ProgramSet * programSet)379 bool FFPLighting::resolveDependencies(ProgramSet* programSet)
380 {
381 Program* vsProgram = programSet->getCpuVertexProgram();
382
383 vsProgram->addDependency(FFP_LIB_COMMON);
384 vsProgram->addDependency(FFP_LIB_LIGHTING);
385
386 return true;
387 }
388
389 //-----------------------------------------------------------------------
addFunctionInvocations(ProgramSet * programSet)390 bool FFPLighting::addFunctionInvocations(ProgramSet* programSet)
391 {
392 Program* vsProgram = programSet->getCpuVertexProgram();
393 Function* vsMain = vsProgram->getEntryPointFunction();
394
395 int internalCounter = 0;
396
397 // Add the global illumination functions.
398 if (false == addGlobalIlluminationInvocation(vsMain, FFP_VS_LIGHTING, internalCounter))
399 return false;
400
401
402 // Add per light functions.
403 for (unsigned int i=0; i < mLightParamsList.size(); ++i)
404 {
405 if (false == addIlluminationInvocation(&mLightParamsList[i], vsMain, FFP_VS_LIGHTING, internalCounter))
406 return false;
407 }
408
409 return true;
410 }
411
412 //-----------------------------------------------------------------------
addGlobalIlluminationInvocation(Function * vsMain,const int groupOrder,int & internalCounter)413 bool FFPLighting::addGlobalIlluminationInvocation(Function* vsMain, const int groupOrder, int& internalCounter)
414 {
415 FunctionInvocation* curFuncInvocation = NULL;
416
417 if ((mTrackVertexColourType & TVC_AMBIENT) == 0 &&
418 (mTrackVertexColourType & TVC_EMISSIVE) == 0)
419 {
420 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
421 curFuncInvocation->pushOperand(mDerivedSceneColour, Operand::OPS_IN);
422 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT);
423 vsMain->addAtomInstance(curFuncInvocation);
424 }
425 else
426 {
427 if (mTrackVertexColourType & TVC_AMBIENT)
428 {
429 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder, internalCounter++);
430 curFuncInvocation->pushOperand(mLightAmbientColour, Operand::OPS_IN);
431 curFuncInvocation->pushOperand(mVSDiffuse, Operand::OPS_IN);
432 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT);
433 vsMain->addAtomInstance(curFuncInvocation);
434 }
435 else
436 {
437 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
438 curFuncInvocation->pushOperand(mDerivedAmbientLightColour, Operand::OPS_IN, Operand::OPM_XYZ);
439 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT, Operand::OPM_XYZ);
440 vsMain->addAtomInstance(curFuncInvocation);
441 }
442
443 if (mTrackVertexColourType & TVC_EMISSIVE)
444 {
445 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++);
446 curFuncInvocation->pushOperand(mVSDiffuse, Operand::OPS_IN);
447 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN);
448 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT);
449 vsMain->addAtomInstance(curFuncInvocation);
450 }
451 else
452 {
453 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++);
454 curFuncInvocation->pushOperand(mSurfaceEmissiveColour, Operand::OPS_IN);
455 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN);
456 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT);
457 vsMain->addAtomInstance(curFuncInvocation);
458 }
459 }
460
461 return true;
462 }
463
464 //-----------------------------------------------------------------------
addIlluminationInvocation(LightParams * curLightParams,Function * vsMain,const int groupOrder,int & internalCounter)465 bool FFPLighting::addIlluminationInvocation(LightParams* curLightParams, Function* vsMain, const int groupOrder, int& internalCounter)
466 {
467 FunctionInvocation* curFuncInvocation = NULL;
468
469 // Merge diffuse colour with vertex colour if need to.
470 if (mTrackVertexColourType & TVC_DIFFUSE)
471 {
472 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder, internalCounter++);
473 curFuncInvocation->pushOperand(mVSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
474 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
475 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
476 vsMain->addAtomInstance(curFuncInvocation);
477 }
478
479 // Merge specular colour with vertex colour if need to.
480 if (mSpecularEnable && mTrackVertexColourType & TVC_SPECULAR)
481 {
482 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder, internalCounter++);
483 curFuncInvocation->pushOperand(mVSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
484 curFuncInvocation->pushOperand(curLightParams->mSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
485 curFuncInvocation->pushOperand(curLightParams->mSpecularColour, Operand::OPS_OUT, Operand::OPM_XYZ);
486 vsMain->addAtomInstance(curFuncInvocation);
487 }
488
489 switch (curLightParams->mType)
490 {
491
492 case Light::LT_DIRECTIONAL:
493 if (mSpecularEnable)
494 {
495 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LIGHT_DIRECTIONAL_DIFFUSESPECULAR, groupOrder, internalCounter++);
496 curFuncInvocation->pushOperand(mWorldViewMatrix, Operand::OPS_IN);
497 curFuncInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
498 curFuncInvocation->pushOperand(mWorldViewITMatrix, Operand::OPS_IN);
499 curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
500 curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN, Operand::OPM_XYZ);
501 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
502 curFuncInvocation->pushOperand(curLightParams->mSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
503 curFuncInvocation->pushOperand(mSurfaceShininess, Operand::OPS_IN);
504 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
505 curFuncInvocation->pushOperand(mVSOutSpecular, Operand::OPS_IN, Operand::OPM_XYZ);
506 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT, Operand::OPM_XYZ);
507 curFuncInvocation->pushOperand(mVSOutSpecular, Operand::OPS_OUT, Operand::OPM_XYZ);
508 vsMain->addAtomInstance(curFuncInvocation);
509 }
510
511 else
512 {
513 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LIGHT_DIRECTIONAL_DIFFUSE, groupOrder, internalCounter++);
514 curFuncInvocation->pushOperand(mWorldViewITMatrix, Operand::OPS_IN);
515 curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
516 curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN, Operand::OPM_XYZ);
517 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
518 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
519 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT, Operand::OPM_XYZ);
520 vsMain->addAtomInstance(curFuncInvocation);
521 }
522 break;
523
524 case Light::LT_POINT:
525 if (mSpecularEnable)
526 {
527 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LIGHT_POINT_DIFFUSESPECULAR, groupOrder, internalCounter++);
528 curFuncInvocation->pushOperand(mWorldViewMatrix, Operand::OPS_IN);
529 curFuncInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
530 curFuncInvocation->pushOperand(mWorldViewITMatrix, Operand::OPS_IN);
531 curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
532 curFuncInvocation->pushOperand(curLightParams->mPosition, Operand::OPS_IN, Operand::OPM_XYZ);
533 curFuncInvocation->pushOperand(curLightParams->mAttenuatParams, Operand::OPS_IN);
534 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
535 curFuncInvocation->pushOperand(curLightParams->mSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
536 curFuncInvocation->pushOperand(mSurfaceShininess, Operand::OPS_IN);
537 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
538 curFuncInvocation->pushOperand(mVSOutSpecular, Operand::OPS_IN, Operand::OPM_XYZ);
539 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT, Operand::OPM_XYZ);
540 curFuncInvocation->pushOperand(mVSOutSpecular, Operand::OPS_OUT, Operand::OPM_XYZ);
541 vsMain->addAtomInstance(curFuncInvocation);
542 }
543 else
544 {
545 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LIGHT_POINT_DIFFUSE, groupOrder, internalCounter++);
546 curFuncInvocation->pushOperand(mWorldViewMatrix, Operand::OPS_IN);
547 curFuncInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
548 curFuncInvocation->pushOperand(mWorldViewITMatrix, Operand::OPS_IN);
549 curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
550 curFuncInvocation->pushOperand(curLightParams->mPosition, Operand::OPS_IN, Operand::OPM_XYZ);
551 curFuncInvocation->pushOperand(curLightParams->mAttenuatParams, Operand::OPS_IN);
552 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
553 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
554 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT, Operand::OPM_XYZ);
555 vsMain->addAtomInstance(curFuncInvocation);
556 }
557
558 break;
559
560 case Light::LT_SPOTLIGHT:
561 if (mSpecularEnable)
562 {
563 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LIGHT_SPOT_DIFFUSESPECULAR, groupOrder, internalCounter++);
564 curFuncInvocation->pushOperand(mWorldViewMatrix, Operand::OPS_IN);
565 curFuncInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
566 curFuncInvocation->pushOperand(mWorldViewITMatrix, Operand::OPS_IN);
567 curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
568 curFuncInvocation->pushOperand(curLightParams->mPosition, Operand::OPS_IN, Operand::OPM_XYZ);
569 curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN, Operand::OPM_XYZ);
570 curFuncInvocation->pushOperand(curLightParams->mAttenuatParams, Operand::OPS_IN);
571 curFuncInvocation->pushOperand(curLightParams->mSpotParams, Operand::OPS_IN);
572 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
573 curFuncInvocation->pushOperand(curLightParams->mSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
574 curFuncInvocation->pushOperand(mSurfaceShininess, Operand::OPS_IN);
575 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
576 curFuncInvocation->pushOperand(mVSOutSpecular, Operand::OPS_IN, Operand::OPM_XYZ);
577 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT, Operand::OPM_XYZ);
578 curFuncInvocation->pushOperand(mVSOutSpecular, Operand::OPS_OUT, Operand::OPM_XYZ);
579 vsMain->addAtomInstance(curFuncInvocation);
580 }
581 else
582 {
583 curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LIGHT_SPOT_DIFFUSE, groupOrder, internalCounter++);
584 curFuncInvocation->pushOperand(mWorldViewMatrix, Operand::OPS_IN);
585 curFuncInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
586 curFuncInvocation->pushOperand(mWorldViewITMatrix, Operand::OPS_IN);
587 curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
588 curFuncInvocation->pushOperand(curLightParams->mPosition, Operand::OPS_IN, Operand::OPM_XYZ);
589 curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN, Operand::OPM_XYZ);
590 curFuncInvocation->pushOperand(curLightParams->mAttenuatParams, Operand::OPS_IN);
591 curFuncInvocation->pushOperand(curLightParams->mSpotParams, Operand::OPS_IN);
592 curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
593 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
594 curFuncInvocation->pushOperand(mVSOutDiffuse, Operand::OPS_OUT, Operand::OPM_XYZ);
595 vsMain->addAtomInstance(curFuncInvocation);
596 }
597 break;
598 }
599
600 return true;
601 }
602
603
604 //-----------------------------------------------------------------------
copyFrom(const SubRenderState & rhs)605 void FFPLighting::copyFrom(const SubRenderState& rhs)
606 {
607 const FFPLighting& rhsLighting = static_cast<const FFPLighting&>(rhs);
608
609 int lightCount[3];
610
611 rhsLighting.getLightCount(lightCount);
612 setLightCount(lightCount);
613 }
614
615 //-----------------------------------------------------------------------
preAddToRenderState(const RenderState * renderState,Pass * srcPass,Pass * dstPass)616 bool FFPLighting::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass)
617 {
618 if (srcPass->getLightingEnabled() == false)
619 return false;
620
621 int lightCount[3];
622
623 renderState->getLightCount(lightCount);
624
625 setTrackVertexColourType(srcPass->getVertexColourTracking());
626
627 if (srcPass->getShininess() > 0.0 &&
628 srcPass->getSpecular() != ColourValue::Black)
629 {
630 setSpecularEnable(true);
631 }
632 else
633 {
634 setSpecularEnable(false);
635 }
636
637 // Case this pass should run once per light(s) -> override the light policy.
638 if (srcPass->getIteratePerLight())
639 {
640
641 // This is the preferred case -> only one type of light is handled.
642 if (srcPass->getRunOnlyForOneLightType())
643 {
644 if (srcPass->getOnlyLightType() == Light::LT_POINT)
645 {
646 lightCount[0] = srcPass->getLightCountPerIteration();
647 lightCount[1] = 0;
648 lightCount[2] = 0;
649 }
650 else if (srcPass->getOnlyLightType() == Light::LT_DIRECTIONAL)
651 {
652 lightCount[0] = 0;
653 lightCount[1] = srcPass->getLightCountPerIteration();
654 lightCount[2] = 0;
655 }
656 else if (srcPass->getOnlyLightType() == Light::LT_SPOTLIGHT)
657 {
658 lightCount[0] = 0;
659 lightCount[1] = 0;
660 lightCount[2] = srcPass->getLightCountPerIteration();
661 }
662 }
663
664 // This is worse case -> all light types expected to be handled.
665 // Can not handle this request in efficient way - throw an exception.
666 else
667 {
668 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
669 "Using iterative lighting method with RT Shader System requires specifying explicit light type.",
670 "FFPLighting::preAddToRenderState");
671 }
672 }
673
674 setLightCount(lightCount);
675
676 return true;
677 }
678
679 //-----------------------------------------------------------------------
setLightCount(const int lightCount[3])680 void FFPLighting::setLightCount(const int lightCount[3])
681 {
682 for (int type=0; type < 3; ++type)
683 {
684 for (int i=0; i < lightCount[type]; ++i)
685 {
686 LightParams curParams;
687
688 if (type == 0)
689 curParams.mType = Light::LT_POINT;
690 else if (type == 1)
691 curParams.mType = Light::LT_DIRECTIONAL;
692 else if (type == 2)
693 curParams.mType = Light::LT_SPOTLIGHT;
694
695 mLightParamsList.push_back(curParams);
696 }
697 }
698 }
699
700 //-----------------------------------------------------------------------
getLightCount(int lightCount[3]) const701 void FFPLighting::getLightCount(int lightCount[3]) const
702 {
703 lightCount[0] = 0;
704 lightCount[1] = 0;
705 lightCount[2] = 0;
706
707 for (unsigned int i=0; i < mLightParamsList.size(); ++i)
708 {
709 const LightParams curParams = mLightParamsList[i];
710
711 if (curParams.mType == Light::LT_POINT)
712 lightCount[0]++;
713 else if (curParams.mType == Light::LT_DIRECTIONAL)
714 lightCount[1]++;
715 else if (curParams.mType == Light::LT_SPOTLIGHT)
716 lightCount[2]++;
717 }
718 }
719
720 //-----------------------------------------------------------------------
getType() const721 const String& FFPLightingFactory::getType() const
722 {
723 return FFPLighting::Type;
724 }
725
726 //-----------------------------------------------------------------------
createInstance(ScriptCompiler * compiler,PropertyAbstractNode * prop,Pass * pass,SGScriptTranslator * translator)727 SubRenderState* FFPLightingFactory::createInstance(ScriptCompiler* compiler,
728 PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator)
729 {
730 if (prop->name == "lighting_stage")
731 {
732 if(prop->values.size() == 1)
733 {
734 String modelType;
735
736 if(false == SGScriptTranslator::getString(prop->values.front(), &modelType))
737 {
738 compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
739 return NULL;
740 }
741
742 if (modelType == "ffp")
743 {
744 return createOrRetrieveInstance(translator);
745 }
746 }
747 }
748
749 return NULL;
750 }
751
752 //-----------------------------------------------------------------------
writeInstance(MaterialSerializer * ser,SubRenderState * subRenderState,Pass * srcPass,Pass * dstPass)753 void FFPLightingFactory::writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState,
754 Pass* srcPass, Pass* dstPass)
755 {
756 ser->writeAttribute(4, "lighting_stage");
757 ser->writeValue("ffp");
758 }
759
760 //-----------------------------------------------------------------------
createInstanceImpl()761 SubRenderState* FFPLightingFactory::createInstanceImpl()
762 {
763 return OGRE_NEW FFPLighting;
764 }
765
766 }
767 }
768
769 #endif
770