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 "OgreShaderFFPTexturing.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 "OgreTextureUnitState.h"
34 #include "OgreFrustum.h"
35 #include "OgrePass.h"
36 
37 namespace Ogre {
38 namespace RTShader {
39 
40 /************************************************************************/
41 /*                                                                      */
42 /************************************************************************/
43 String FFPTexturing::Type = "FFP_Texturing";
44 #define _INT_VALUE(f) (*(int*)(&(f)))
45 
46 const String c_ParamTexelEx("texel_");
47 
48 //-----------------------------------------------------------------------
FFPTexturing()49 FFPTexturing::FFPTexturing()
50 {
51 }
52 
53 //-----------------------------------------------------------------------
getType() const54 const String& FFPTexturing::getType() const
55 {
56 	return Type;
57 }
58 
59 //-----------------------------------------------------------------------
getExecutionOrder() const60 int	FFPTexturing::getExecutionOrder() const
61 {
62 	return FFP_TEXTURING;
63 }
64 
65 //-----------------------------------------------------------------------
resolveParameters(ProgramSet * programSet)66 bool FFPTexturing::resolveParameters(ProgramSet* programSet)
67 {
68 	for (unsigned int i=0; i < mTextureUnitParamsList.size(); ++i)
69 	{
70 		TextureUnitParams* curParams = &mTextureUnitParamsList[i];
71 
72 		if (false == resolveUniformParams(curParams, programSet))
73 			return false;
74 
75 
76 		if (false == resolveFunctionsParams(curParams, programSet))
77 			return false;
78 	}
79 
80 
81 	return true;
82 }
83 
84 //-----------------------------------------------------------------------
resolveUniformParams(TextureUnitParams * textureUnitParams,ProgramSet * programSet)85 bool FFPTexturing::resolveUniformParams(TextureUnitParams* textureUnitParams, ProgramSet* programSet)
86 {
87 	Program* vsProgram = programSet->getCpuVertexProgram();
88 	Program* psProgram = programSet->getCpuFragmentProgram();
89 	bool hasError = false;
90 
91 	// Resolve texture sampler parameter.
92 	textureUnitParams->mTextureSampler = psProgram->resolveParameter(textureUnitParams->mTextureSamplerType, textureUnitParams->mTextureSamplerIndex, (uint16)GPV_GLOBAL, "gTextureSampler");
93 	hasError |= !(textureUnitParams->mTextureSampler.get());
94 
95 	// Resolve texture matrix parameter.
96 	if (needsTextureMatrix(textureUnitParams->mTextureUnitState))
97 	{
98 		textureUnitParams->mTextureMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_TEXTURE_MATRIX, textureUnitParams->mTextureSamplerIndex);
99 		hasError |= !(textureUnitParams->mTextureMatrix.get());
100 	}
101 
102 	switch (textureUnitParams->mTexCoordCalcMethod)
103 	{
104 	case TEXCALC_NONE:
105 		break;
106 
107 	// Resolve World + View matrices.
108 	case TEXCALC_ENVIRONMENT_MAP:
109 	case TEXCALC_ENVIRONMENT_MAP_PLANAR:
110 	case TEXCALC_ENVIRONMENT_MAP_NORMAL:
111 		//TODO: change the following 'mWorldITMatrix' member to 'mWorldViewITMatrix'
112 		mWorldITMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLDVIEW_MATRIX, 0);
113 		mViewMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_VIEW_MATRIX, 0);
114 		mWorldMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLD_MATRIX, 0);
115 
116 		hasError |= !(mWorldITMatrix.get())  || !(mViewMatrix.get()) || !(mWorldITMatrix.get());
117 		break;
118 
119 	case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
120 		mWorldMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLD_MATRIX, 0);
121 		mWorldITMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLD_MATRIX, 0);
122 		mViewMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_VIEW_MATRIX, 0);
123 
124 		hasError |= !(mWorldMatrix.get()) || !(mWorldITMatrix.get()) || !(mViewMatrix.get());
125 		break;
126 
127 	case TEXCALC_PROJECTIVE_TEXTURE:
128 
129 		mWorldMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLD_MATRIX, 0);
130 		textureUnitParams->mTextureViewProjImageMatrix = vsProgram->resolveParameter(GCT_MATRIX_4X4, -1, (uint16)GPV_LIGHTS, "gTexViewProjImageMatrix");
131 
132 		hasError |= !(mWorldMatrix.get()) || !(textureUnitParams->mTextureViewProjImageMatrix.get());
133 
134 		const TextureUnitState::EffectMap&		effectMap = textureUnitParams->mTextureUnitState->getEffects();
135 		TextureUnitState::EffectMap::const_iterator	effi;
136 
137 		for (effi = effectMap.begin(); effi != effectMap.end(); ++effi)
138 		{
139 			if (effi->second.type == TextureUnitState::ET_PROJECTIVE_TEXTURE)
140 			{
141 				textureUnitParams->mTextureProjector = effi->second.frustum;
142 				break;
143 			}
144 		}
145 
146 		hasError |= !(textureUnitParams->mTextureProjector);
147 		break;
148 	}
149 
150 
151 	if (hasError)
152 	{
153 		OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
154 				"Not all parameters could be constructed for the sub-render state.",
155 				"FFPTexturing::resolveUniformParams" );
156 	}
157 	return true;
158 }
159 
160 
161 
162 //-----------------------------------------------------------------------
resolveFunctionsParams(TextureUnitParams * textureUnitParams,ProgramSet * programSet)163 bool FFPTexturing::resolveFunctionsParams(TextureUnitParams* textureUnitParams, ProgramSet* programSet)
164 {
165 	Program* vsProgram = programSet->getCpuVertexProgram();
166 	Program* psProgram = programSet->getCpuFragmentProgram();
167 	Function* vsMain   = vsProgram->getEntryPointFunction();
168 	Function* psMain   = psProgram->getEntryPointFunction();
169 	Parameter::Content texCoordContent = Parameter::SPC_UNKNOWN;
170 	bool hasError = false;
171 
172 	switch (textureUnitParams->mTexCoordCalcMethod)
173 	{
174 		case TEXCALC_NONE:
175 			// Resolve explicit vs input texture coordinates.
176 
177 			if (textureUnitParams->mTextureMatrix.get() == NULL)
178 				texCoordContent = Parameter::Content(Parameter::SPC_TEXTURE_COORDINATE0 + textureUnitParams->mTextureUnitState->getTextureCoordSet());
179 
180 			textureUnitParams->mVSInputTexCoord = vsMain->resolveInputParameter(Parameter::SPS_TEXTURE_COORDINATES,
181 				textureUnitParams->mTextureUnitState->getTextureCoordSet(),
182 				Parameter::Content(Parameter::SPC_TEXTURE_COORDINATE0 + textureUnitParams->mTextureUnitState->getTextureCoordSet()),
183 				textureUnitParams->mVSInTextureCoordinateType);
184 			hasError |= !(textureUnitParams->mVSInputTexCoord.get());
185 			break;
186 
187 		case TEXCALC_ENVIRONMENT_MAP:
188 		case TEXCALC_ENVIRONMENT_MAP_PLANAR:
189 		case TEXCALC_ENVIRONMENT_MAP_NORMAL:
190 			// Resolve vertex normal.
191 			mVSInputPos = vsMain->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4);
192 			mVSInputNormal = vsMain->resolveInputParameter(Parameter::SPS_NORMAL, 0, Parameter::SPC_NORMAL_OBJECT_SPACE, GCT_FLOAT3);
193 			hasError |= !(mVSInputNormal.get()) || !(mVSInputPos.get());
194 			break;
195 
196 		case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
197 
198 			// Resolve vertex normal.
199 			mVSInputNormal = vsMain->resolveInputParameter(Parameter::SPS_NORMAL, 0, Parameter::SPC_NORMAL_OBJECT_SPACE, GCT_FLOAT3);
200 			// Resolve vertex position.
201 			mVSInputPos = vsMain->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4);
202 
203 			hasError |= !(mVSInputNormal.get()) || !(mVSInputPos.get());
204 			break;
205 
206 		case TEXCALC_PROJECTIVE_TEXTURE:
207 			// Resolve vertex position.
208 			mVSInputPos = vsMain->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4);
209 			hasError |= !(mVSInputPos.get());
210 			break;
211 	}
212 
213 	// Resolve vs output texture coordinates.
214 	textureUnitParams->mVSOutputTexCoord = vsMain->resolveOutputParameter(Parameter::SPS_TEXTURE_COORDINATES,
215 		-1,
216 		texCoordContent,
217 		textureUnitParams->mVSOutTextureCoordinateType);
218 
219 	// Resolve ps input texture coordinates.
220 	textureUnitParams->mPSInputTexCoord = psMain->resolveInputParameter(Parameter::SPS_TEXTURE_COORDINATES,
221 		textureUnitParams->mVSOutputTexCoord->getIndex(),
222 		textureUnitParams->mVSOutputTexCoord->getContent(),
223 		textureUnitParams->mVSOutTextureCoordinateType);
224 
225 	const ShaderParameterList& inputParams = psMain->getInputParameters();
226 	const ShaderParameterList& localParams = psMain->getLocalParameters();
227 
228 	mPSDiffuse = psMain->getParameterByContent(inputParams, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
229 	if (mPSDiffuse.get() == NULL)
230 	{
231 		mPSDiffuse = psMain->getParameterByContent(localParams, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
232 	}
233 
234 	mPSSpecular = psMain->getParameterByContent(inputParams, Parameter::SPC_COLOR_SPECULAR, GCT_FLOAT4);
235 	if (mPSSpecular.get() == NULL)
236 	{
237 		mPSSpecular = psMain->getParameterByContent(localParams, Parameter::SPC_COLOR_SPECULAR, GCT_FLOAT4);
238 	}
239 
240 	mPSOutDiffuse = psMain->resolveOutputParameter(Parameter::SPS_COLOR, 0, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
241 
242 	hasError |= !(textureUnitParams->mVSOutputTexCoord.get()) || !(textureUnitParams->mPSInputTexCoord.get()) ||
243 		!(mPSDiffuse.get()) || !(mPSSpecular.get()) || !(mPSOutDiffuse.get());
244 
245 	if (hasError)
246 	{
247 		OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
248 				"Not all parameters could be constructed for the sub-render state.",
249 				"FFPTexturing::resolveFunctionsParams" );
250 	}
251 	return true;
252 }
253 
254 //-----------------------------------------------------------------------
resolveDependencies(ProgramSet * programSet)255 bool FFPTexturing::resolveDependencies(ProgramSet* programSet)
256 {
257 	Program* vsProgram = programSet->getCpuVertexProgram();
258 	Program* psProgram = programSet->getCpuFragmentProgram();
259 
260 	vsProgram->addDependency(FFP_LIB_COMMON);
261 	vsProgram->addDependency(FFP_LIB_TEXTURING);
262 	psProgram->addDependency(FFP_LIB_COMMON);
263 	psProgram->addDependency(FFP_LIB_TEXTURING);
264 
265 	return true;
266 }
267 
268 //-----------------------------------------------------------------------
addFunctionInvocations(ProgramSet * programSet)269 bool FFPTexturing::addFunctionInvocations(ProgramSet* programSet)
270 {
271 	Program* vsProgram = programSet->getCpuVertexProgram();
272 	Program* psProgram = programSet->getCpuFragmentProgram();
273 	Function* vsMain   = vsProgram->getEntryPointFunction();
274 	Function* psMain   = psProgram->getEntryPointFunction();
275 	int internalCounter = 0;
276 
277 	for (unsigned int i=0; i < mTextureUnitParamsList.size(); ++i)
278 	{
279 		TextureUnitParams* curParams = &mTextureUnitParamsList[i];
280 
281 		if (false == addVSFunctionInvocations(curParams, vsMain))
282 			return false;
283 
284 		if (false == addPSFunctionInvocations(curParams, psMain, internalCounter))
285 			return false;
286 	}
287 
288 	return true;
289 }
290 
291 //-----------------------------------------------------------------------
addVSFunctionInvocations(TextureUnitParams * textureUnitParams,Function * vsMain)292 bool FFPTexturing::addVSFunctionInvocations(TextureUnitParams* textureUnitParams, Function* vsMain)
293 {
294 	FunctionInvocation* texCoordCalcFunc = NULL;
295 
296 
297 	switch (textureUnitParams->mTexCoordCalcMethod)
298 	{
299 	case TEXCALC_NONE:
300 		if (textureUnitParams->mTextureMatrix.get() == NULL)
301 		{
302 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
303 
304 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSInputTexCoord, Operand::OPS_IN);
305 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
306 		}
307 		else
308 		{
309 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM_TEXCOORD,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
310 
311 			texCoordCalcFunc->pushOperand(textureUnitParams->mTextureMatrix, Operand::OPS_IN);
312 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSInputTexCoord, Operand::OPS_IN);
313 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
314 		}
315 		break;
316 
317 	case TEXCALC_ENVIRONMENT_MAP:
318 	case TEXCALC_ENVIRONMENT_MAP_PLANAR:
319 		if (textureUnitParams->mTextureMatrix.get() == NULL)
320 		{
321 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_GENERATE_TEXCOORD_ENV_SPHERE,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
322 
323 			//TODO: Add field member mWorldViewITMatrix
324 			texCoordCalcFunc->pushOperand(mWorldMatrix, Operand::OPS_IN);
325 			texCoordCalcFunc->pushOperand(mViewMatrix, Operand::OPS_IN);
326 			texCoordCalcFunc->pushOperand(mWorldITMatrix, Operand::OPS_IN);
327 			texCoordCalcFunc->pushOperand(mVSInputPos, Operand::OPS_IN);
328 			texCoordCalcFunc->pushOperand(mVSInputNormal, Operand::OPS_IN);
329 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
330 		}
331 		else
332 		{
333 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_GENERATE_TEXCOORD_ENV_SPHERE,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
334 
335 			texCoordCalcFunc->pushOperand(mWorldMatrix, Operand::OPS_IN);
336 			texCoordCalcFunc->pushOperand(mViewMatrix, Operand::OPS_IN);
337 			texCoordCalcFunc->pushOperand(mWorldITMatrix, Operand::OPS_IN);
338 			texCoordCalcFunc->pushOperand(mVSInputPos, Operand::OPS_IN);
339 			texCoordCalcFunc->pushOperand(mVSInputNormal, Operand::OPS_IN);
340 			texCoordCalcFunc->pushOperand(textureUnitParams->mTextureMatrix, Operand::OPS_IN);
341 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
342 		}
343 		break;
344 
345 
346 	case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
347 		if (textureUnitParams->mTextureMatrix.get() == NULL)
348 		{
349 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_GENERATE_TEXCOORD_ENV_REFLECT,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
350 
351 			texCoordCalcFunc->pushOperand(mWorldMatrix, Operand::OPS_IN);
352 			texCoordCalcFunc->pushOperand(mWorldITMatrix, Operand::OPS_IN);
353 			texCoordCalcFunc->pushOperand(mViewMatrix, Operand::OPS_IN);
354 			texCoordCalcFunc->pushOperand(mVSInputNormal, Operand::OPS_IN);
355 			texCoordCalcFunc->pushOperand(mVSInputPos, Operand::OPS_IN);
356 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
357 		}
358 		else
359 		{
360 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_GENERATE_TEXCOORD_ENV_REFLECT,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
361 
362 			texCoordCalcFunc->pushOperand(mWorldMatrix, Operand::OPS_IN);
363 			texCoordCalcFunc->pushOperand(mWorldITMatrix, Operand::OPS_IN);
364 			texCoordCalcFunc->pushOperand(mViewMatrix, Operand::OPS_IN);
365 			texCoordCalcFunc->pushOperand(textureUnitParams->mTextureMatrix, Operand::OPS_IN);
366 			texCoordCalcFunc->pushOperand(mVSInputNormal, Operand::OPS_IN);
367 			texCoordCalcFunc->pushOperand(mVSInputPos, Operand::OPS_IN);
368 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
369 		}
370 		break;
371 
372 	case TEXCALC_ENVIRONMENT_MAP_NORMAL:
373 		if (textureUnitParams->mTextureMatrix.get() == NULL)
374 		{
375 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_GENERATE_TEXCOORD_ENV_NORMAL,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
376 
377 			texCoordCalcFunc->pushOperand(mWorldITMatrix, Operand::OPS_IN);
378 			texCoordCalcFunc->pushOperand(mViewMatrix, Operand::OPS_IN);
379 			texCoordCalcFunc->pushOperand(mVSInputNormal, Operand::OPS_IN);
380 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
381 		}
382 		else
383 		{
384 			texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_GENERATE_TEXCOORD_ENV_NORMAL,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
385 
386 			texCoordCalcFunc->pushOperand(mWorldITMatrix, Operand::OPS_IN);
387 			texCoordCalcFunc->pushOperand(mViewMatrix, Operand::OPS_IN);
388 			texCoordCalcFunc->pushOperand(textureUnitParams->mTextureMatrix, Operand::OPS_IN);
389 			texCoordCalcFunc->pushOperand(mVSInputNormal, Operand::OPS_IN);
390 			texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
391 		}
392 		break;
393 
394 	case TEXCALC_PROJECTIVE_TEXTURE:
395 
396 		texCoordCalcFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_GENERATE_TEXCOORD_PROJECTION,  FFP_VS_TEXTURING, textureUnitParams->mTextureSamplerIndex);
397 
398 		texCoordCalcFunc->pushOperand(mWorldMatrix, Operand::OPS_IN);
399 		texCoordCalcFunc->pushOperand(textureUnitParams->mTextureViewProjImageMatrix, Operand::OPS_IN);
400 		texCoordCalcFunc->pushOperand(mVSInputPos, Operand::OPS_IN);
401 		texCoordCalcFunc->pushOperand(textureUnitParams->mVSOutputTexCoord, Operand::OPS_OUT);
402 
403 		break;
404 	}
405 
406 	if (texCoordCalcFunc != NULL)
407 		vsMain->addAtomInstance(texCoordCalcFunc);
408 
409 	return true;
410 }
411 //-----------------------------------------------------------------------
addPSFunctionInvocations(TextureUnitParams * textureUnitParams,Function * psMain,int & internalCounter)412 bool FFPTexturing::addPSFunctionInvocations(TextureUnitParams* textureUnitParams, Function* psMain, int& internalCounter)
413 {
414 	const LayerBlendModeEx& colourBlend = textureUnitParams->mTextureUnitState->getColourBlendMode();
415 	const LayerBlendModeEx& alphaBlend  = textureUnitParams->mTextureUnitState->getAlphaBlendMode();
416 	ParameterPtr source1;
417 	ParameterPtr source2;
418 	int groupOrder = FFP_PS_TEXTURING;
419 
420 
421 	// Add texture sampling code.
422 	ParameterPtr texel = psMain->resolveLocalParameter(Parameter::SPS_UNKNOWN, 0, c_ParamTexelEx + StringConverter::toString(textureUnitParams->mTextureSamplerIndex), GCT_FLOAT4);
423 	addPSSampleTexelInvocation(textureUnitParams, psMain, texel, FFP_PS_SAMPLING, internalCounter);
424 
425 	// Build colour argument for source1.
426 	source1 = psMain->resolveLocalParameter(Parameter::SPS_UNKNOWN, 0, "source1", GCT_FLOAT4);
427 
428 	addPSArgumentInvocations(psMain, source1, texel,
429 		textureUnitParams->mTextureSamplerIndex,
430 		colourBlend.source1, colourBlend.colourArg1,
431 		colourBlend.alphaArg1, false, groupOrder, internalCounter);
432 
433 	// Build colour argument for source2.
434 	source2 = psMain->resolveLocalParameter(Parameter::SPS_UNKNOWN, 0, "source2", GCT_FLOAT4);
435 
436 	addPSArgumentInvocations(psMain, source2, texel,
437 		textureUnitParams->mTextureSamplerIndex,
438 		colourBlend.source2, colourBlend.colourArg2,
439 		colourBlend.alphaArg2, false, groupOrder, internalCounter);
440 
441 	bool needDifferentAlphaBlend = false;
442 	if (alphaBlend.operation != colourBlend.operation ||
443 		alphaBlend.source1 != colourBlend.source1 ||
444 		alphaBlend.source2 != colourBlend.source2 ||
445 		colourBlend.source1 == LBS_MANUAL ||
446 		colourBlend.source2 == LBS_MANUAL ||
447 		alphaBlend.source1 == LBS_MANUAL ||
448 		alphaBlend.source2 == LBS_MANUAL)
449 		needDifferentAlphaBlend = true;
450 
451 	// Build colours blend
452 	addPSBlendInvocations(psMain, source1, source2, texel,
453 		textureUnitParams->mTextureSamplerIndex,
454 		colourBlend, groupOrder, internalCounter,
455 		needDifferentAlphaBlend ? Operand::OPM_XYZ : Operand::OPM_ALL);
456 
457 	// Case we need different alpha channel code.
458 	if (needDifferentAlphaBlend)
459 	{
460 		// Build alpha argument for source1.
461 		addPSArgumentInvocations(psMain, source1, texel,
462 			textureUnitParams->mTextureSamplerIndex,
463 			alphaBlend.source1, alphaBlend.colourArg1,
464 			alphaBlend.alphaArg1, true, groupOrder, internalCounter);
465 
466 		// Build alpha argument for source2.
467 		addPSArgumentInvocations(psMain, source2, texel,
468 			textureUnitParams->mTextureSamplerIndex,
469 			alphaBlend.source2, alphaBlend.colourArg2,
470 			alphaBlend.alphaArg2, true, groupOrder, internalCounter);
471 
472 		// Build alpha blend
473 		addPSBlendInvocations(psMain, source1, source2, texel,
474 			textureUnitParams->mTextureSamplerIndex,
475 			alphaBlend, groupOrder, internalCounter,
476 			Operand::OPM_W);
477 	}
478 
479 
480 
481 	return true;
482 }
483 
484 //-----------------------------------------------------------------------
addPSSampleTexelInvocation(TextureUnitParams * textureUnitParams,Function * psMain,const ParameterPtr & texel,int groupOrder,int & internalCounter)485 void FFPTexturing::addPSSampleTexelInvocation(TextureUnitParams* textureUnitParams, Function* psMain,
486 											  const ParameterPtr& texel, int groupOrder, int& internalCounter)
487 {
488 	FunctionInvocation* curFuncInvocation = NULL;
489 
490 	if (textureUnitParams->mTexCoordCalcMethod == TEXCALC_PROJECTIVE_TEXTURE)
491 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE_PROJ, groupOrder, internalCounter++);
492 	else
493 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE, groupOrder, internalCounter++);
494 
495 	curFuncInvocation->pushOperand(textureUnitParams->mTextureSampler, Operand::OPS_IN);
496 	curFuncInvocation->pushOperand(textureUnitParams->mPSInputTexCoord, Operand::OPS_IN);
497 	curFuncInvocation->pushOperand(texel, Operand::OPS_OUT);
498 	psMain->addAtomInstance(curFuncInvocation);
499 }
500 
501 
502 //-----------------------------------------------------------------------
addPSArgumentInvocations(Function * psMain,ParameterPtr arg,ParameterPtr texel,int samplerIndex,LayerBlendSource blendSrc,const ColourValue & colourValue,Real alphaValue,bool isAlphaArgument,const int groupOrder,int & internalCounter)503 void FFPTexturing::addPSArgumentInvocations(Function* psMain,
504 											 ParameterPtr arg,
505 											 ParameterPtr texel,
506 											 int samplerIndex,
507 											 LayerBlendSource blendSrc,
508 											 const ColourValue& colourValue,
509 											 Real alphaValue,
510 											 bool isAlphaArgument,
511 											 const int groupOrder,
512 											 int& internalCounter)
513 {
514 	FunctionInvocation* curFuncInvocation = NULL;
515 
516 	switch(blendSrc)
517 	{
518 	case LBS_CURRENT:
519 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
520 		if (samplerIndex == 0)
521 			curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN);
522 		else
523 			curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_IN);
524 		curFuncInvocation->pushOperand(arg, Operand::OPS_OUT);
525 		psMain->addAtomInstance(curFuncInvocation);
526 		break;
527 	case LBS_TEXTURE:
528 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
529 		curFuncInvocation->pushOperand(texel, Operand::OPS_IN);
530 		curFuncInvocation->pushOperand(arg, Operand::OPS_OUT);
531 		psMain->addAtomInstance(curFuncInvocation);
532 		break;
533 	case LBS_DIFFUSE:
534 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
535 		curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN);
536 		curFuncInvocation->pushOperand(arg, Operand::OPS_OUT);
537 		psMain->addAtomInstance(curFuncInvocation);
538 		break;
539 	case LBS_SPECULAR:
540 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
541 		curFuncInvocation->pushOperand(mPSSpecular, Operand::OPS_IN);
542 		curFuncInvocation->pushOperand(arg, Operand::OPS_OUT);
543 		psMain->addAtomInstance(curFuncInvocation);
544 		break;
545 
546 	case LBS_MANUAL:
547 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_CONSTRUCT, groupOrder, internalCounter++);
548 
549 		if (isAlphaArgument)
550 		{
551 			curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(alphaValue), Operand::OPS_IN);
552 		}
553 		else
554 		{
555 			curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(colourValue.r), Operand::OPS_IN);
556 			curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(colourValue.g), Operand::OPS_IN);
557 			curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(colourValue.b), Operand::OPS_IN);
558 			curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(colourValue.a), Operand::OPS_IN);
559 		}
560 
561 		curFuncInvocation->pushOperand(arg, Operand::OPS_OUT);
562 		psMain->addAtomInstance(curFuncInvocation);
563 		break;
564 	}
565 }
566 
567 //-----------------------------------------------------------------------
addPSBlendInvocations(Function * psMain,ParameterPtr arg1,ParameterPtr arg2,ParameterPtr texel,int samplerIndex,const LayerBlendModeEx & blendMode,const int groupOrder,int & internalCounter,int targetChannels)568 void FFPTexturing::addPSBlendInvocations(Function* psMain,
569 										  ParameterPtr arg1,
570 										  ParameterPtr arg2,
571 										  ParameterPtr texel,
572 										  int samplerIndex,
573 										  const LayerBlendModeEx& blendMode,
574 										  const int groupOrder,
575 										  int& internalCounter,
576 										  int targetChannels)
577 {
578 	FunctionInvocation* curFuncInvocation = NULL;
579 
580 	switch(blendMode.operation)
581 	{
582 	case LBX_SOURCE1:
583 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
584 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
585 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
586 		psMain->addAtomInstance(curFuncInvocation);
587 		break;
588 	case LBX_SOURCE2:
589 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
590 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
591 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
592 		psMain->addAtomInstance(curFuncInvocation);
593 		break;
594 	case LBX_MODULATE:
595 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder, internalCounter++);
596 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
597 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
598 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
599 		psMain->addAtomInstance(curFuncInvocation);
600 		break;
601 	case LBX_MODULATE_X2:
602 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATEX2, groupOrder, internalCounter++);
603 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
604 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
605 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
606 		psMain->addAtomInstance(curFuncInvocation);
607 		break;
608 	case LBX_MODULATE_X4:
609 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATEX4, groupOrder, internalCounter++);
610 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
611 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
612 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
613 		psMain->addAtomInstance(curFuncInvocation);
614 		break;
615 	case LBX_ADD:
616 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++);
617 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
618 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
619 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
620 		psMain->addAtomInstance(curFuncInvocation);
621 		break;
622 	case LBX_ADD_SIGNED:
623 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADDSIGNED, groupOrder, internalCounter++);
624 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
625 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
626 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
627 		psMain->addAtomInstance(curFuncInvocation);
628 		break;
629 	case LBX_ADD_SMOOTH:
630 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADDSMOOTH, groupOrder, internalCounter++);
631 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
632 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
633 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
634 		psMain->addAtomInstance(curFuncInvocation);
635 		break;
636 	case LBX_SUBTRACT:
637 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SUBTRACT, groupOrder, internalCounter++);
638 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
639 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
640 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
641 		psMain->addAtomInstance(curFuncInvocation);
642 		break;
643 	case LBX_BLEND_DIFFUSE_ALPHA:
644 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SUBTRACT, groupOrder, internalCounter++);
645 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
646 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
647 		curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_W);
648 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
649 		psMain->addAtomInstance(curFuncInvocation);
650 		break;
651 	case LBX_BLEND_TEXTURE_ALPHA:
652 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LERP, groupOrder, internalCounter++);
653 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
654 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
655 		curFuncInvocation->pushOperand(texel, Operand::OPS_IN, Operand::OPM_W);
656 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
657 		psMain->addAtomInstance(curFuncInvocation);
658 		break;
659 	case LBX_BLEND_CURRENT_ALPHA:
660 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LERP, groupOrder, internalCounter++);
661 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
662 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
663 
664 		if (samplerIndex == 0)
665 			curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_W);
666 		else
667 			curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_IN, Operand::OPM_W);
668 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
669 		psMain->addAtomInstance(curFuncInvocation);
670 		break;
671 	case LBX_BLEND_MANUAL:
672 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LERP, groupOrder, internalCounter++);
673 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
674 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
675 		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(blendMode.factor), Operand::OPS_IN);
676 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
677 		psMain->addAtomInstance(curFuncInvocation);
678 		break;
679 	case LBX_DOTPRODUCT:
680 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_DOTPRODUCT, groupOrder, internalCounter++);
681 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
682 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
683 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
684 		psMain->addAtomInstance(curFuncInvocation);
685 		break;
686 	case LBX_BLEND_DIFFUSE_COLOUR:
687 		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LERP, groupOrder, internalCounter++);
688 		curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
689 		curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
690 		curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN);
691 		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);
692 		psMain->addAtomInstance(curFuncInvocation);
693 		break;
694 	}
695 }
696 
697 //-----------------------------------------------------------------------
getTexCalcMethod(TextureUnitState * textureUnitState)698 TexCoordCalcMethod FFPTexturing::getTexCalcMethod(TextureUnitState* textureUnitState)
699 {
700 	TexCoordCalcMethod						texCoordCalcMethod = TEXCALC_NONE;
701 	const TextureUnitState::EffectMap&		effectMap = textureUnitState->getEffects();
702 	TextureUnitState::EffectMap::const_iterator	effi;
703 
704 	for (effi = effectMap.begin(); effi != effectMap.end(); ++effi)
705 	{
706 		switch (effi->second.type)
707 		{
708 		case TextureUnitState::ET_ENVIRONMENT_MAP:
709 			if (effi->second.subtype == TextureUnitState::ENV_CURVED)
710 			{
711 				texCoordCalcMethod = TEXCALC_ENVIRONMENT_MAP;
712 			}
713 			else if (effi->second.subtype == TextureUnitState::ENV_PLANAR)
714 			{
715 				texCoordCalcMethod = TEXCALC_ENVIRONMENT_MAP_PLANAR;
716 			}
717 			else if (effi->second.subtype == TextureUnitState::ENV_REFLECTION)
718 			{
719 				texCoordCalcMethod = TEXCALC_ENVIRONMENT_MAP_REFLECTION;
720 			}
721 			else if (effi->second.subtype == TextureUnitState::ENV_NORMAL)
722 			{
723 				texCoordCalcMethod = TEXCALC_ENVIRONMENT_MAP_NORMAL;
724 			}
725 			break;
726 		case TextureUnitState::ET_UVSCROLL:
727 		case TextureUnitState::ET_USCROLL:
728 		case TextureUnitState::ET_VSCROLL:
729 		case TextureUnitState::ET_ROTATE:
730 		case TextureUnitState::ET_TRANSFORM:
731 			break;
732 		case TextureUnitState::ET_PROJECTIVE_TEXTURE:
733 			texCoordCalcMethod = TEXCALC_PROJECTIVE_TEXTURE;
734 			break;
735 		}
736 	}
737 
738 	return texCoordCalcMethod;
739 }
740 
741 //-----------------------------------------------------------------------
needsTextureMatrix(TextureUnitState * textureUnitState)742 bool FFPTexturing::needsTextureMatrix(TextureUnitState* textureUnitState)
743 {
744 	const TextureUnitState::EffectMap&		effectMap = textureUnitState->getEffects();
745 	TextureUnitState::EffectMap::const_iterator	effi;
746 
747 	for (effi = effectMap.begin(); effi != effectMap.end(); ++effi)
748 	{
749 		switch (effi->second.type)
750 		{
751 
752 		case TextureUnitState::ET_UVSCROLL:
753 		case TextureUnitState::ET_USCROLL:
754 		case TextureUnitState::ET_VSCROLL:
755 		case TextureUnitState::ET_ROTATE:
756 		case TextureUnitState::ET_TRANSFORM:
757 		case TextureUnitState::ET_ENVIRONMENT_MAP:
758 		case TextureUnitState::ET_PROJECTIVE_TEXTURE:
759 			return true;
760 		}
761 	}
762 
763 	const Ogre::Matrix4 matTexture = textureUnitState->getTextureTransform();
764 
765 	// Resolve texture matrix parameter.
766 	if (matTexture != Matrix4::IDENTITY)
767 		return true;
768 
769 	return false;
770 }
771 
772 
773 //-----------------------------------------------------------------------
copyFrom(const SubRenderState & rhs)774 void FFPTexturing::copyFrom(const SubRenderState& rhs)
775 {
776 	const FFPTexturing& rhsTexture = static_cast<const FFPTexturing&>(rhs);
777 
778 	setTextureUnitCount(rhsTexture.getTextureUnitCount());
779 
780 	for (unsigned int i=0; i < rhsTexture.getTextureUnitCount(); ++i)
781 	{
782 		setTextureUnit(i, rhsTexture.mTextureUnitParamsList[i].mTextureUnitState);
783 	}
784 }
785 
786 //-----------------------------------------------------------------------
preAddToRenderState(const RenderState * renderState,Pass * srcPass,Pass * dstPass)787 bool FFPTexturing::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass)
788 {
789 	//count the number of texture units we need to process
790 	size_t validTexUnits = 0;
791 	for (unsigned short i=0; i < srcPass->getNumTextureUnitStates(); ++i)
792 	{
793 		if (isProcessingNeeded(srcPass->getTextureUnitState(i)))
794 		{
795 			++validTexUnits;
796 		}
797 	}
798 
799 	setTextureUnitCount(validTexUnits);
800 
801 	// Build texture stage sub states.
802 	for (unsigned short i=0; i < srcPass->getNumTextureUnitStates(); ++i)
803 	{
804 		TextureUnitState* texUnitState = srcPass->getTextureUnitState(i);
805 
806 		if (isProcessingNeeded(texUnitState))
807 		{
808 			setTextureUnit(i, texUnitState);
809 		}
810 	}
811 
812 	return true;
813 }
814 
815 //-----------------------------------------------------------------------
updateGpuProgramsParams(Renderable * rend,Pass * pass,const AutoParamDataSource * source,const LightList * pLightList)816 void FFPTexturing::updateGpuProgramsParams(Renderable* rend, Pass* pass, const AutoParamDataSource* source,
817 											  const LightList* pLightList)
818 {
819 	for (unsigned int i=0; i < mTextureUnitParamsList.size(); ++i)
820 	{
821 		TextureUnitParams* curParams = &mTextureUnitParamsList[i];
822 
823 		if (curParams->mTextureProjector != NULL && curParams->mTextureViewProjImageMatrix.get() != NULL)
824 		{
825 			Matrix4 matTexViewProjImage;
826 
827 			matTexViewProjImage =
828 				Matrix4::CLIPSPACE2DTOIMAGESPACE *
829 				curParams->mTextureProjector->getProjectionMatrixWithRSDepth() *
830 				curParams->mTextureProjector->getViewMatrix();
831 
832 			curParams->mTextureViewProjImageMatrix->setGpuParameter(matTexViewProjImage);
833 		}
834 	}
835 }
836 
837 //-----------------------------------------------------------------------
setTextureUnitCount(size_t count)838 void FFPTexturing::setTextureUnitCount(size_t count)
839 {
840 	mTextureUnitParamsList.resize(count);
841 
842 	for (unsigned int i=0; i < count; ++i)
843 	{
844 		TextureUnitParams& curParams = mTextureUnitParamsList[i];
845 
846 		curParams.mTextureUnitState				= NULL;
847 		curParams.mTextureProjector				= NULL;
848 		curParams.mTextureSamplerIndex			= 0;
849 		curParams.mTextureSamplerType			= GCT_SAMPLER2D;
850 		curParams.mVSInTextureCoordinateType	= GCT_FLOAT2;
851 		curParams.mVSOutTextureCoordinateType	= GCT_FLOAT2;
852 	}
853 }
854 
855 //-----------------------------------------------------------------------
setTextureUnit(unsigned short index,TextureUnitState * textureUnitState)856 void FFPTexturing::setTextureUnit(unsigned short index, TextureUnitState* textureUnitState)
857 {
858 	if (index >= mTextureUnitParamsList.size())
859 	{
860 		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
861 			"FFPTexturing unit index out of bounds !!!",
862 			"FFPTexturing::setTextureUnit");
863 	}
864 
865 	if (textureUnitState->getBindingType() == TextureUnitState::BT_VERTEX)
866 	{
867 		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
868 			"FFP Texture unit does not support vertex texture fetch !!!",
869 			"FFPTexturing::setTextureUnit");
870 	}
871 
872 
873 	TextureUnitParams& curParams = mTextureUnitParamsList[index];
874 
875 
876 	curParams.mTextureSamplerIndex = index;
877 	curParams.mTextureUnitState    = textureUnitState;
878 
879 	switch (curParams.mTextureUnitState->getTextureType())
880 	{
881 	case TEX_TYPE_1D:
882 		curParams.mTextureSamplerType = GCT_SAMPLER1D;
883 		curParams.mVSInTextureCoordinateType = GCT_FLOAT1;
884 		break;
885 	case TEX_TYPE_2D:
886 		curParams.mTextureSamplerType = GCT_SAMPLER2D;
887 		curParams.mVSInTextureCoordinateType = GCT_FLOAT2;
888 		break;
889     case TEX_TYPE_2D_RECT:
890         curParams.mTextureSamplerType = GCT_SAMPLERRECT;
891         curParams.mVSInTextureCoordinateType = GCT_FLOAT2;
892         break;
893     case TEX_TYPE_2D_ARRAY:
894         curParams.mTextureSamplerType = GCT_SAMPLER2DARRAY;
895         curParams.mVSInTextureCoordinateType = GCT_FLOAT3;
896         break;
897 	case TEX_TYPE_3D:
898 		curParams.mTextureSamplerType = GCT_SAMPLER3D;
899 		curParams.mVSInTextureCoordinateType = GCT_FLOAT3;
900 		break;
901 	case TEX_TYPE_CUBE_MAP:
902 		curParams.mTextureSamplerType = GCT_SAMPLERCUBE;
903 		curParams.mVSInTextureCoordinateType = GCT_FLOAT3;
904 		break;
905 	}
906 
907 	 curParams.mVSOutTextureCoordinateType = curParams.mVSInTextureCoordinateType;
908 	 curParams.mTexCoordCalcMethod = getTexCalcMethod(curParams.mTextureUnitState);
909 
910 	 if (curParams.mTexCoordCalcMethod == TEXCALC_PROJECTIVE_TEXTURE)
911 		 curParams.mVSOutTextureCoordinateType = GCT_FLOAT3;
912 }
913 
914 //-----------------------------------------------------------------------
isProcessingNeeded(TextureUnitState * texUnitState)915 bool FFPTexturing::isProcessingNeeded(TextureUnitState* texUnitState)
916 {
917 	return texUnitState->getBindingType() == TextureUnitState::BT_FRAGMENT;
918 }
919 
920 
921 //-----------------------------------------------------------------------
getType() const922 const String& FFPTexturingFactory::getType() const
923 {
924 	return FFPTexturing::Type;
925 }
926 
927 //-----------------------------------------------------------------------
createInstance(ScriptCompiler * compiler,PropertyAbstractNode * prop,Pass * pass,SGScriptTranslator * translator)928 SubRenderState*	FFPTexturingFactory::createInstance(ScriptCompiler* compiler,
929 												 PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator)
930 {
931 	if (prop->name == "texturing_stage")
932 	{
933 		if(prop->values.size() == 1)
934 		{
935 			String modelType;
936 
937 			if(false == SGScriptTranslator::getString(prop->values.front(), &modelType))
938 			{
939 				compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
940 				return NULL;
941 			}
942 
943 			if (modelType == "ffp")
944 			{
945 				return createOrRetrieveInstance(translator);
946 			}
947 		}
948 	}
949 
950 	return NULL;
951 }
952 
953 //-----------------------------------------------------------------------
writeInstance(MaterialSerializer * ser,SubRenderState * subRenderState,Pass * srcPass,Pass * dstPass)954 void FFPTexturingFactory::writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState,
955 									 Pass* srcPass, Pass* dstPass)
956 {
957 	ser->writeAttribute(4, "texturing_stage");
958 	ser->writeValue("ffp");
959 }
960 
961 //-----------------------------------------------------------------------
createInstanceImpl()962 SubRenderState*	FFPTexturingFactory::createInstanceImpl()
963 {
964 	return OGRE_NEW FFPTexturing;
965 }
966 
967 
968 }
969 }
970 
971 #endif
972