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 Also see acknowledgements in Readme.html
9
10 You may use this sample code for anything you like, it is not covered by the
11 same license as the rest of the engine.
12 -----------------------------------------------------------------------------
13 */
14
15
16 #include "GBufferMaterialGenerator.h"
17
18 #include "OgreMaterialManager.h"
19 #include "OgreGpuProgramManager.h"
20 #include "OgreRoot.h"
21 #include "OgreStringConverter.h"
22 #include "OgreHighLevelGpuProgramManager.h"
23 #include "OgreTechnique.h"
24
25 using namespace Ogre;
26
27 //Use this directive to control whether you are writing projective (regular) or linear depth.
28 #define WRITE_LINEAR_DEPTH
29
30 //This is the concrete implementation of the material generator.
31 class GBufferMaterialGeneratorImpl : public MaterialGenerator::Impl
32 {
33 public:
GBufferMaterialGeneratorImpl(const String & baseName)34 GBufferMaterialGeneratorImpl(const String& baseName) :
35 mBaseName(baseName)
36 {
37 mIsSm4 = GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0_level_9_1");
38 mIsGLSL = (GpuProgramManager::getSingleton().isSyntaxSupported("glsl") || GpuProgramManager::getSingleton().isSyntaxSupported("glsles")) &&
39 !(GpuProgramManager::getSingleton().isSyntaxSupported("vs_1_1") || GpuProgramManager::getSingleton().isSyntaxSupported("arbvp1"));
40 }
41
42 protected:
43 String mBaseName;
44 bool mIsSm4;
45 bool mIsGLSL;
46 virtual GpuProgramPtr generateVertexShader(MaterialGenerator::Perm permutation);
47 virtual GpuProgramPtr generateFragmentShader(MaterialGenerator::Perm permutation);
48 virtual MaterialPtr generateTemplateMaterial(MaterialGenerator::Perm permutation);
49
50 };
51
GBufferMaterialGenerator()52 GBufferMaterialGenerator::GBufferMaterialGenerator() {
53 vsMask = VS_MASK;
54 fsMask = FS_MASK;
55 matMask = MAT_MASK;
56 materialBaseName = "DeferredShading/GBuffer/";
57 mImpl = new GBufferMaterialGeneratorImpl(materialBaseName);
58 }
59
generateVertexShader(MaterialGenerator::Perm permutation)60 GpuProgramPtr GBufferMaterialGeneratorImpl::generateVertexShader(MaterialGenerator::Perm permutation)
61 {
62 StringStream ss;
63
64 if(mIsGLSL)
65 {
66 int shadingLangVersion = Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion();
67 const char *inSemantic = shadingLangVersion >= 150 ? "in" : "attribute";
68 const char *outSemantic = shadingLangVersion >= 150 ? "out" : "varying";
69
70 if(GpuProgramManager::getSingleton().isSyntaxSupported("glsles"))
71 {
72 ss << "#version 300 es" << std::endl;
73 ss << "precision mediump int;" << std::endl;
74 ss << "precision mediump float;" << std::endl;
75 }
76 else
77 ss << "#version " << shadingLangVersion << std::endl;
78
79 ss << inSemantic << " vec4 vertex;" << std::endl;
80 ss << inSemantic << " vec3 normal;" << std::endl;
81
82 uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8;
83 for (uint32 i = 0; i < numTexCoords; i++)
84 {
85 ss << inSemantic << " vec2 uv" << i << ';' << std::endl;
86 }
87
88 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
89 {
90 ss << inSemantic << " vec3 tangent;" << std::endl;
91 }
92
93 //TODO : Skinning inputs
94 ss << std::endl;
95
96 #ifdef WRITE_LINEAR_DEPTH
97 ss << outSemantic << " vec3 oViewPos;" << std::endl;
98 #else
99 ss << outSemantic << " float oDepth;" << std::endl;
100 #endif
101 ss << outSemantic << " vec3 oNormal;" << std::endl;
102 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
103 {
104 ss << outSemantic << " vec3 oTangent;" << std::endl;
105 ss << outSemantic << " vec3 oBiNormal;" << std::endl;
106 }
107 for (uint32 i = 0; i < numTexCoords; i++)
108 {
109 ss << outSemantic << " vec2 oUv" << i << ";" << std::endl;
110 }
111
112 ss << std::endl;
113
114 ss << "uniform mat4 cWorldViewProj;" << std::endl;
115 ss << "uniform mat4 cWorldView;" << std::endl;
116
117 ss << "void main()" << std::endl;
118
119 ss << "{" << std::endl;
120 ss << " gl_Position = cWorldViewProj * vertex;" << std::endl;
121 ss << " oNormal = (cWorldView * vec4(normal,0)).xyz;" << std::endl;
122 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
123 {
124 ss << " oTangent = (cWorldView * vec4(tangent,0)).xyz;" << std::endl;
125 ss << " oBiNormal = cross(oNormal, oTangent);" << std::endl;
126 }
127
128 #ifdef WRITE_LINEAR_DEPTH
129 ss << " oViewPos = (cWorldView * vertex).xyz;" << std::endl;
130 #else
131 ss << " oDepth = gl_Position.w;" << std::endl;
132 #endif
133
134 for (uint32 i=0; i<numTexCoords; i++) {
135 ss << " oUv" << i << " = uv" << i << ';' << std::endl;
136 }
137
138 ss << "}" << std::endl;
139
140 String programSource = ss.str();
141 String programName = mBaseName + "VP_" + StringConverter::toString(permutation);
142
143 #if OGRE_DEBUG_MODE
144 LogManager::getSingleton().getDefaultLog()->logMessage(programSource);
145 #endif
146
147 // Create shader object
148 HighLevelGpuProgramPtr ptrProgram;
149 if(GpuProgramManager::getSingleton().isSyntaxSupported("glsles"))
150 {
151 ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName,
152 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
153 "glsles", GPT_VERTEX_PROGRAM);
154 ptrProgram->setParameter("syntax", "glsles");
155 }
156 else
157 {
158 ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName,
159 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
160 "glsl", GPT_VERTEX_PROGRAM);
161 }
162 ptrProgram->setSource(programSource);
163
164 const GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
165 params->setNamedAutoConstant("cWorldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
166 params->setNamedAutoConstant("cWorldView", GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
167 ptrProgram->load();
168
169 return GpuProgramPtr(ptrProgram);
170 }
171 else
172 {
173 ss << "void ToGBufferVP(" << std::endl;
174 ss << " float4 iPosition : POSITION," << std::endl;
175 ss << " float3 iNormal : NORMAL," << std::endl;
176
177 uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8;
178 for (uint32 i=0; i<numTexCoords; i++)
179 {
180 ss << " float2 iUV" << i << " : TEXCOORD" << i << ',' << std::endl;
181 }
182
183 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
184 {
185 if(mIsSm4)
186 {
187 ss << " float3 iTangent : TANGENT," << std::endl;
188 }
189 else
190 {
191 ss << " float3 iTangent : TANGENT0," << std::endl;
192 }
193 }
194
195 //TODO : Skinning inputs
196 ss << std::endl;
197
198
199
200 ss << " out float4 oPosition : " ;
201 if(mIsSm4)
202 {
203 ss << "SV_";
204 }
205 ss << "POSITION," << std::endl;
206 #ifdef WRITE_LINEAR_DEPTH
207 ss << " out float3 oViewPos : TEXCOORD0," << std::endl;
208 #else
209 ss << " out float oDepth : TEXCOORD0," << std::endl;
210 #endif
211 ss << " out float3 oNormal : TEXCOORD1," << std::endl;
212 int texCoordNum = 2;
213 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
214 {
215 ss << " out float3 oTangent : TEXCOORD" << texCoordNum++ << ',' << std::endl;
216 ss << " out float3 oBiNormal : TEXCOORD" << texCoordNum++ << ',' << std::endl;
217 }
218 for (uint32 i=0; i<numTexCoords; i++)
219 {
220 ss << " out float2 oUV" << i << " : TEXCOORD" << texCoordNum++ << ',' << std::endl;
221 }
222
223 ss << std::endl;
224
225 ss << " uniform float4x4 cWorldViewProj," << std::endl;
226 ss << " uniform float4x4 cWorldView" << std::endl;
227
228 ss << " )" << std::endl;
229
230
231 ss << "{" << std::endl;
232 ss << " oPosition = mul(cWorldViewProj, iPosition);" << std::endl;
233 ss << " oNormal = mul(cWorldView, float4(iNormal,0)).xyz;" << std::endl;
234 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
235 {
236 ss << " oTangent = mul(cWorldView, float4(iTangent,0)).xyz;" << std::endl;
237 ss << " oBiNormal = cross(oNormal, oTangent);" << std::endl;
238 }
239
240 #ifdef WRITE_LINEAR_DEPTH
241 ss << " oViewPos = mul(cWorldView, iPosition).xyz;" << std::endl;
242 #else
243 ss << " oDepth = oPosition.w;" << std::endl;
244 #endif
245
246 for (uint32 i=0; i<numTexCoords; i++) {
247 ss << " oUV" << i << " = iUV" << i << ';' << std::endl;
248 }
249
250 ss << "}" << std::endl;
251
252 String programSource = ss.str();
253 String programName = mBaseName + "VP_" + StringConverter::toString(permutation);
254
255 #if OGRE_DEBUG_MODE
256 LogManager::getSingleton().getDefaultLog()->logMessage(programSource);
257 #endif
258
259 // Create shader object
260 HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(
261 programName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
262 "cg", GPT_VERTEX_PROGRAM);
263 ptrProgram->setSource(programSource);
264 ptrProgram->setParameter("entry_point","ToGBufferVP");
265 if(mIsSm4)
266 {
267 ptrProgram->setParameter("profiles","vs_4_0");
268 }
269 else
270 {
271 ptrProgram->setParameter("profiles","vs_1_1 arbvp1");
272 }
273
274 const GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
275 params->setNamedAutoConstant("cWorldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
276 params->setNamedAutoConstant("cWorldView", GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
277 ptrProgram->load();
278
279 return GpuProgramPtr(ptrProgram);
280 }
281 }
282
generateFragmentShader(MaterialGenerator::Perm permutation)283 GpuProgramPtr GBufferMaterialGeneratorImpl::generateFragmentShader(MaterialGenerator::Perm permutation)
284 {
285 StringStream ss;
286
287 if(mIsGLSL)
288 {
289 int shadingLangVersion = Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion();
290 const char *inSemantic = shadingLangVersion >= 150 ? "in" : "varying";
291 const char *outData = shadingLangVersion >= 150 ? "fragData" : "gl_FragData";
292 const char *textureFunc = shadingLangVersion >= 150 ? "texture" : "texture2D";
293 if(GpuProgramManager::getSingleton().isSyntaxSupported("glsles"))
294 {
295 ss << "#version 300 es" << std::endl;
296 ss << "precision mediump int;" << std::endl;
297 ss << "precision mediump float;" << std::endl;
298 }
299 else
300 {
301 ss << "#version " << shadingLangVersion << std::endl;
302 if(shadingLangVersion >= 150)
303 {
304 ss << "out vec4 fragData[2];";
305 }
306 }
307 #ifdef WRITE_LINEAR_DEPTH
308 ss << inSemantic << " vec3 oViewPos;" << std::endl;
309 #else
310 ss << inSemantic << " float oDepth;" << std::endl;
311 #endif
312 ss << inSemantic << " vec3 oNormal;" << std::endl;
313
314 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
315 {
316 ss << inSemantic << " vec3 oTangent;" << std::endl;
317 ss << inSemantic << " vec3 oBiNormal;" << std::endl;
318 }
319
320 uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8;
321 for (uint32 i = 0; i < numTexCoords; i++)
322 {
323 ss << inSemantic << " vec2 oUv" << i << ';' << std::endl;
324 }
325
326 ss << std::endl;
327
328 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
329 {
330 ss << "uniform sampler2D sNormalMap;" << std::endl;
331 }
332
333 uint32 numTextures = permutation & GBufferMaterialGenerator::GBP_TEXTURE_MASK;
334 for (uint32 i = 0; i < numTextures; i++)
335 {
336 ss << "uniform sampler2D sTex" << i << ";" << std::endl;
337 }
338 if (numTextures == 0 || permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR)
339 {
340 ss << "uniform vec4 cDiffuseColour;" << std::endl;
341 }
342
343 #ifdef WRITE_LINEAR_DEPTH
344 ss << "uniform float cFarDistance;" << std::endl;
345 #endif
346
347 ss << "uniform float cSpecularity;" << std::endl;
348
349 ss << "void main()" << std::endl;
350 ss << "{" << std::endl;
351
352 if (numTexCoords > 0 && numTextures > 0)
353 {
354 ss << outData << "[0].rgb = " << textureFunc << "(sTex0, oUv0).rgb;" << std::endl;
355 if (permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR)
356 {
357 ss << outData << "[0].rgb *= cDiffuseColour.rgb;" << std::endl;
358 }
359 }
360 else
361 {
362 ss << outData << "[0].rgb = cDiffuseColour.rgb;" << std::endl;
363 }
364
365 ss << outData << "[0].a = cSpecularity;" << std::endl;
366 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
367 {
368 ss << " vec3 texNormal = (" << textureFunc << "(sNormalMap, oUv0).rgb-0.5)*2.0;" << std::endl;
369 ss << " mat3 normalRotation = mat3(oTangent, oBiNormal, oNormal);" << std::endl;
370 ss << outData << "[1].rgb = normalize(texNormal * normalRotation);" << std::endl;
371 }
372 else
373 {
374 ss << outData << "[1].rgb = normalize(oNormal);" << std::endl;
375 }
376 ss << outData << "[1].rgb = normalize(oNormal);" << std::endl;
377 #ifdef WRITE_LINEAR_DEPTH
378 ss << outData << "[1].a = length(oViewPos) / cFarDistance;" << std::endl;
379 #else
380 ss << outData << "[1].a = oDepth;" << std::endl;
381 #endif
382
383 ss << "}" << std::endl;
384
385 String programSource = ss.str();
386 String programName = mBaseName + "FP_" + StringConverter::toString(permutation);
387
388 #if OGRE_DEBUG_MODE
389 LogManager::getSingleton().getDefaultLog()->logMessage(programSource);
390 #endif
391
392 // Create shader object
393 HighLevelGpuProgramPtr ptrProgram;
394 if(GpuProgramManager::getSingleton().isSyntaxSupported("glsles"))
395 {
396 ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName,
397 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
398 "glsles", GPT_FRAGMENT_PROGRAM);
399 ptrProgram->setParameter("syntax", "glsles");
400 }
401 else
402 {
403 ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName,
404 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
405 "glsl", GPT_FRAGMENT_PROGRAM);
406 }
407 ptrProgram->setSource(programSource);
408
409 const GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
410 params->setNamedAutoConstant("cSpecularity", GpuProgramParameters::ACT_SURFACE_SHININESS);
411 if (numTextures == 0 || permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR)
412 {
413 params->setNamedAutoConstant("cDiffuseColour", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
414 }
415
416 // Bind samplers
417 int samplerNum = 0;
418 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
419 {
420 params->setNamedConstant("sNormalMap", samplerNum++);
421 }
422 for (uint32 i = 0; i < numTextures; i++, samplerNum++)
423 {
424 params->setNamedConstant("sTex" + StringConverter::toString(i), samplerNum);
425 }
426
427 #ifdef WRITE_LINEAR_DEPTH
428 //TODO : Should this be the distance to the far corner, not the far clip distance?
429 params->setNamedAutoConstant("cFarDistance", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
430 #endif
431
432 ptrProgram->load();
433 return GpuProgramPtr(ptrProgram);
434 }
435 else
436 {
437 ss << "void ToGBufferFP(" << std::endl;
438 if(mIsSm4)
439 {
440 ss << "float4 oPosition : SV_POSITION," << std::endl;
441 }
442
443 #ifdef WRITE_LINEAR_DEPTH
444 ss << " float3 iViewPos : TEXCOORD0," << std::endl;
445 #else
446 ss << " float1 iDepth : TEXCOORD0," << std::endl;
447 #endif
448 ss << " float3 iNormal : TEXCOORD1," << std::endl;
449
450 int texCoordNum = 2;
451 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
452 {
453 ss << " float3 iTangent : TEXCOORD" << texCoordNum++ << ',' << std::endl;
454 ss << " float3 iBiNormal : TEXCOORD" << texCoordNum++ << ',' << std::endl;
455 }
456
457 uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8;
458 for (uint32 i=0; i<numTexCoords; i++)
459 {
460 ss << " float2 iUV" << i << " : TEXCOORD" << texCoordNum++ << ',' << std::endl;
461 }
462
463 ss << std::endl;
464
465 ss << " out float4 oColor0 : COLOR0," << std::endl;
466 ss << " out float4 oColor1 : COLOR1," << std::endl;
467
468 ss << std::endl;
469
470 int samplerNum = 0;
471 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
472 {
473 if(mIsSm4)
474 {
475 ss << " uniform sampler2D sNormalMap : register(s" << samplerNum++ << ")," << std::endl;
476 }
477 else
478 {
479 ss << " uniform sampler sNormalMap : register(s" << samplerNum++ << ")," << std::endl;
480 }
481 }
482 uint32 numTextures = permutation & GBufferMaterialGenerator::GBP_TEXTURE_MASK;
483 for (uint32 i=0; i<numTextures; i++) {
484 if(mIsSm4)
485 {
486 ss << " uniform sampler2D sTex" << i << " : register(s" << samplerNum++ << ")," << std::endl;
487 }
488 else
489 {
490 ss << " uniform sampler sTex" << i << " : register(s" << samplerNum++ << ")," << std::endl;
491 }
492 }
493 if (numTextures == 0 || permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR)
494 {
495 ss << " uniform float4 cDiffuseColour," << std::endl;
496 }
497
498 #ifdef WRITE_LINEAR_DEPTH
499 ss << " uniform float cFarDistance," << std::endl;
500 #endif
501
502 ss << " uniform float cSpecularity" << std::endl;
503
504 ss << " )" << std::endl;
505
506
507 ss << "{" << std::endl;
508
509 if (numTexCoords > 0 && numTextures > 0)
510 {
511 ss << " oColor0.rgb = tex2D(sTex0, iUV0).rgb;" << std::endl;
512 if (permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR)
513 {
514 ss << " oColor0.rgb *= cDiffuseColour.rgb;" << std::endl;
515 }
516 }
517 else
518 {
519 ss << " oColor0.rgb = cDiffuseColour.rgb;" << std::endl;
520 }
521
522
523 ss << " oColor0.a = cSpecularity;" << std::endl;
524 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
525 {
526 ss << " float3 texNormal = (tex2D(sNormalMap, iUV0).rgb-0.5)*2;" << std::endl;
527 ss << " float3x3 normalRotation = float3x3(iTangent, iBiNormal, iNormal);" << std::endl;
528 ss << " oColor1.rgb = normalize(mul(texNormal, normalRotation));" << std::endl;
529 } else
530 {
531 ss << " oColor1.rgb = normalize(iNormal);" << std::endl;
532 }
533 #ifdef WRITE_LINEAR_DEPTH
534 ss << " oColor1.a = length(iViewPos) / cFarDistance;" << std::endl;
535 #else
536 ss << " oColor1.a = iDepth;" << std::endl;
537 #endif
538
539 ss << "}" << std::endl;
540
541 String programSource = ss.str();
542 String programName = mBaseName + "FP_" + StringConverter::toString(permutation);
543
544 #if OGRE_DEBUG_MODE
545 LogManager::getSingleton().getDefaultLog()->logMessage(programSource);
546 #endif
547
548 // Create shader object
549 HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(
550 programName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
551 "cg", GPT_FRAGMENT_PROGRAM);
552 ptrProgram->setSource(programSource);
553 ptrProgram->setParameter("entry_point","ToGBufferFP");
554 if(mIsSm4)
555 {
556 ptrProgram->setParameter("profiles","ps_4_0");
557 }
558 else
559 {
560 ptrProgram->setParameter("profiles","ps_2_0 arbfp1");
561 }
562
563 const GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
564 params->setNamedAutoConstant("cSpecularity", GpuProgramParameters::ACT_SURFACE_SHININESS);
565 if (numTextures == 0 || permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR)
566 {
567 params->setNamedAutoConstant("cDiffuseColour", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
568 }
569
570 #ifdef WRITE_LINEAR_DEPTH
571 //TODO : Should this be the distance to the far corner, not the far clip distance?
572 params->setNamedAutoConstant("cFarDistance", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
573 #endif
574
575 ptrProgram->load();
576 return GpuProgramPtr(ptrProgram);
577 }
578 }
579
generateTemplateMaterial(MaterialGenerator::Perm permutation)580 MaterialPtr GBufferMaterialGeneratorImpl::generateTemplateMaterial(MaterialGenerator::Perm permutation)
581 {
582 String matName = mBaseName + "Mat_" + StringConverter::toString(permutation);
583
584 MaterialPtr matPtr = MaterialManager::getSingleton().create
585 (matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
586 Pass* pass = matPtr->getTechnique(0)->getPass(0);
587 pass->setName(mBaseName + "Pass_" + StringConverter::toString(permutation));
588 pass->setLightingEnabled(false);
589 if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP)
590 {
591 pass->createTextureUnitState();
592 }
593 uint32 numTextures = permutation & GBufferMaterialGenerator::GBP_TEXTURE_MASK;
594 for (uint32 i=0; i<numTextures; i++)
595 {
596 pass->createTextureUnitState();
597 }
598
599 return matPtr;
600 }
601