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