1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_MaterialState.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision: 26187 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_GFX_MATERIALSTATE_H_
17 #define NW_GFX_MATERIALSTATE_H_
18 
19 #include <nw/types.h>
20 #include <nw/gfx/gfx_ActivateCommand.h>
21 #include <nw/gfx/gfx_GraphicsDevice.h>
22 
23 // このマクロを定義するとマテリアルの個々の要素の設定に関するプロファイルを行います。
24 // #define NW_MATERIAL_PROFILE
25 
26 // このマクロを定義するとマテリアルを設定します。
27 #define MATERIAL_SET_ENABLED
28 
29 namespace nw
30 {
31 namespace os
32 {
33 class IAllocator;
34 }
35 
36 namespace gfx
37 {
38 
39 namespace internal
40 {
41 
42 // OpenGL 標準仕様の射影変換行列を生成する
43 nn::math::Matrix34*
44 CreateMatrixForLinearShadowMapTexture(nn::math::Matrix34* pOut, f32 coeff, f32 nearp, f32 farp);
45 
46 //---------------------------------------------------------------------------
47 //! @brief        マテリアル内容を GL に設定するクラスです。
48 //---------------------------------------------------------------------------
49 class MaterialState
50 {
51 public:
52     //----------------------------------------
53     //! @name マテリアル関連
54     //@{
55 
56     //---------------------------------------------------------------------------
57     //! @brief        シェーダーパラメータを設定します。
58     //!
59     //! @param[in]    shaderProgram シェーダープログラムです。
60     //! @param[in]    material  マテリアルです。
61     //---------------------------------------------------------------------------
62     static NW_INLINE void ActivateShaderParameter(
63         const ShaderProgram* shaderProgram,
64         const ResMaterial material);
65 
66     //---------------------------------------------------------------------------
67     //! @brief        フラグメントライトに関するパラメータを設定します。
68     //!
69     //! @param[in]    sceneEnvironment シーン環境です。
70     //! @param[in]    shaderProgram シェーダープログラムです。
71     //! @param[in]    material マテリアルです。
72     //---------------------------------------------------------------------------
73     static NW_INLINE void ActivateFragmentLightParameters(
74         const SceneEnvironment& sceneEnvironment,
75         const ShaderProgram* shaderProgram,
76         const ResMaterial material);
77 
78     //---------------------------------------------------------------------------
79     //! @brief        シェーディングに関するパラメータを設定します。
80     //!
81     //! @param[in]    sceneEnvironment シーン環境です。
82     //! @param[in]    shaderProgram シェーダープログラムです。
83     //! @param[in]    material マテリアルです。
84     //---------------------------------------------------------------------------
85     static NW_INLINE void ActivateShadingParameters(
86         const SceneEnvironment& sceneEnvironment,
87         const ShaderProgram* shaderProgram,
88         const ResMaterial material);
89 
90     //---------------------------------------------------------------------------
91     //! @brief        ラスタライゼーションを設定します。
92     //!
93     //! @param[in]    rasterization ラスタライゼーションです。
94     //---------------------------------------------------------------------------
95     static NW_INLINE void ActivateRasterization(const ResRasterization rasterization);
96 
97     //---------------------------------------------------------------------------
98     //! @brief        フラグメントライティングテーブルを設定します。
99     //!
100     //! @param[in]    fragmentLighting      フラグメントライティングです。
101     //! @param[in]    fragmentLightingTable フラグメントライティングテーブルです。
102     //---------------------------------------------------------------------------
103     static void ActivateFragmentLightingTable(
104         const ResFragmentLighting fragmentLighting,
105         const ResFragmentLightingTable fragmentLightingTable);
106 
107     //---------------------------------------------------------------------------
108     //! @brief        テクスチャ座標の設定をおこないます。
109     //!
110     //! @param[in]    renderContext レンダーコンテキストです。
111     //! @param[in]    shaderProgram シェーダープログラムです。
112     //! @param[in]    texCoordMaterial  テクスチャ座標の設定に利用するマテリアルです。
113     //---------------------------------------------------------------------------
114     static void ActivateTextureCoordinators(
115         RenderContext* renderContext,
116         const ShaderProgram* shaderProgram,
117         const ResMaterial texCoordMaterial);
118 
119     //---------------------------------------------------------------------------
120     //! @brief        パーティクル独自のテクスチャ座標設定をおこないます。
121     //!
122     //! @param[in]    renderContext レンダーコンテキストです。
123     //! @param[in]    shaderProgram シェーダープログラムです。
124     //! @param[in]    texCoordMaterial  テクスチャ座標の設定に利用するマテリアルです。
125     //---------------------------------------------------------------------------
126     static void ActivateParticleTextureCoordinators(
127         RenderContext* renderContext,
128         const ShaderProgram* shaderProgram,
129         const ResMaterial texCoordMaterial);
130 
131     //---------------------------------------------------------------------------
132     //! @brief        マテリアルカラーを設定します。
133     //!
134     //! @param[in]    sceneEnvironment シーン環境です。
135     //! @param[in]    shaderProgram シェーダープログラムです。
136     //! @param[in]    materialColor マテリアルカラーです。
137     //! @param[in]    useReflection 反射テーブルが有効どうかを表すフラグです。
138     //---------------------------------------------------------------------------
139     static NW_INLINE void ActivateMaterialColor(
140         const SceneEnvironment& sceneEnvironment,
141         const ShaderProgram* shaderProgram,
142         ResMaterialColor materialColor,
143         bool useReflection);
144 
145     //---------------------------------------------------------------------------
146     //! @brief        フラグメントライティングを設定します。
147     //!
148     //! @param[in]    sceneEnvironment シーン環境です。
149     //! @param[in]    fragmentLighting 設定するフラグメントライティングです。
150     //---------------------------------------------------------------------------
151     static NW_INLINE void ActivateFragmentLighting(
152         const SceneEnvironment& sceneEnvironment,
153         const ResFragmentLighting fragmentLighting);
154 
155     //---------------------------------------------------------------------------
156     //! @brief        テクスチャマッパーの設定をおこないます。
157     //!
158     //! @param[in]    texMapperMaterial  テクスチャマッパーを利用するマテリアルです。
159     //---------------------------------------------------------------------------
160     static NW_INLINE void ActivateTextureMappers(const ResMaterial texMapperMaterial);
161 
162 
163     //---------------------------------------------------------------------------
164     //! @brief        パーティクル独自のテクスチャマッパー設定をおこないます。
165     //!
166     //! @param[in]    texMapperMaterial  テクスチャマッパーを利用するマテリアルです。
167     //---------------------------------------------------------------------------
168     static NW_INLINE void ActivateParticleTextureMappers(const ResMaterial texMapperMaterial);
169 
170     //---------------------------------------------------------------------------
171     //! @brief        プロシージャルテクスチャマッパーの設定をおこないます。
172     //!
173     //! @param[in]    renderContext   レンダーコンテキストです。
174     //! @param[in]    shaderProgram シェーダープログラムです。
175     //! @param[in]    material  プロシージャルテクスチャマッパを利用するマテリアルです。
176     //---------------------------------------------------------------------------
177     static NW_INLINE void ActivateProceduralTextureMapper(
178         RenderContext* renderContext,
179         const ShaderProgram* shaderProgram,
180         const ResMaterial material);
181 
182     //---------------------------------------------------------------------------
183     //! @brief        テクスチャコンバイナを設定します。
184     //!
185     //! @param[in]    fragmentShader フラグメントシェーダーです。
186     //! @param[in]    materialColor  マテリアルカラーです。
187     //---------------------------------------------------------------------------
188     static NW_INLINE void ActivateTextureCombiners(
189         const ResFragmentShader fragmentShader,
190         const ResMaterialColor materialColor);
191 
192     //---------------------------------------------------------------------------
193     //! @brief        アルファテストを設定します。
194     //!
195     //! @param[in]    alphaTest アルファテストです。
196     //---------------------------------------------------------------------------
197     static NW_INLINE void ActivateAlphaTest(const ResAlphaTest alphaTest);
198 
199     //---------------------------------------------------------------------------
200     //! @brief        フラグメントオペレーションを設定します。
201     //!
202     //! @param[in]    fragmentOperation フラグメントオペレーションです。
203     //---------------------------------------------------------------------------
204     static NW_INLINE void ActivateFragmentOperation(const ResFragmentOperation fragmentOperation);
205 
206     //---------------------------------------------------------------------------
207     //! @brief        フォグに関するパラメータを設定します。
208     //!
209     //! @param[in]    material マテリアルです。
210     //---------------------------------------------------------------------------
211     static NW_INLINE void ActivateFogParameters(
212         const SceneEnvironment& sceneEnvironment,
213         const ResMaterial material);
214 
215     //@}
216 
217 private:
218     //! コンスタントカラーを取得します。
219     static NW_INLINE u32 GetConstantColorU32(
220         ResTextureCombiner::Constant constant,
221         const ResMaterialColor materialColor);
222 
223     //---------------------------------------------------------------------------
224     //! @brief        デプスオペレーションを設定します。
225     //!
226     //! @param[in]    depthOperation デプスオペレーションです。
227     //---------------------------------------------------------------------------
228     static NW_INLINE void ActivateDepthOperation(const ResDepthOperation depthOperation);
229 
230     //---------------------------------------------------------------------------
231     //! @brief        ステンシルオペレーションを設定します。
232     //!
233     //! @param[in]    stencilOperation ステンシルオペレーションです。
234     //---------------------------------------------------------------------------
235     static NW_INLINE void ActivateStencilOperation(const ResStencilOperation stencilOperation);
236 
237     //---------------------------------------------------------------------------
238     //! @brief        ブレンドオペレーションを設定します。
239     //!
240     //! @param[in]    blendOperation ブレンドオペレーションです。
241     //---------------------------------------------------------------------------
242     static NW_INLINE void ActivateBlendOperation(const ResBlendOperation blendOperation);
243 
244     //---------------------------------------------------------------------------
245     //! @brief        計算方式別にテクスチャマトリクスを設定します。
246     //!
247     //! @param[out]   textureMatrix  設定されるマトリクスです。
248     //! @param[in]    mode           計算方式の指定です。
249     //! @param[in]    scaleS         S 軸のスケール値です。
250     //! @param[in]    scaleT         T 軸のスケール値です。
251     //! @param[in]    rotate         回転値です。
252     //! @param[in]    translateS     S 軸の移動値です。
253     //! @param[in]    translateT     T 軸の移動値です。
254     //---------------------------------------------------------------------------
255     static math::MTX44* SetupTextureMatrix(
256         math::MTX44* textureMatrix,
257         ResTextureCoordinator::MappingMatrixMode mode,
258         float scaleS, float scaleT,
259         float rotate,
260         float translateS, float translateT);
261 };
262 
263 //----------------------------------------
264 NW_INLINE u32
GetConstantColorU32(ResTextureCombiner::Constant constant,const ResMaterialColor materialColor)265 MaterialState::GetConstantColorU32(
266     ResTextureCombiner::Constant constant,
267     const ResMaterialColor materialColor)
268 {
269     switch ( constant )
270     {
271     case ResTextureCombiner::CONSTANT0: return  materialColor.GetConstant0U32();
272     case ResTextureCombiner::CONSTANT1: return  materialColor.GetConstant1U32();
273     case ResTextureCombiner::CONSTANT2: return  materialColor.GetConstant2U32();
274     case ResTextureCombiner::CONSTANT3: return  materialColor.GetConstant3U32();
275     case ResTextureCombiner::CONSTANT4: return  materialColor.GetConstant4U32();
276     case ResTextureCombiner::CONSTANT5: return  materialColor.GetConstant5U32();
277     case ResTextureCombiner::EMISSION:  return  materialColor.GetEmissionU32();
278     case ResTextureCombiner::AMBIENT:   return  materialColor.GetAmbientU32();
279     case ResTextureCombiner::DIFFUSE:   return  materialColor.GetDiffuseU32();
280     case ResTextureCombiner::SPECULAR0: return  materialColor.GetSpecular0U32();
281     case ResTextureCombiner::SPECULAR1: return  materialColor.GetSpecular1U32();
282     default:
283         NW_FATAL_ERROR("Illegal constant name");
284         return materialColor.GetConstant0U32();
285     }
286 }
287 
288 //----------------------------------------
289 NW_INLINE void
ActivateFogParameters(const SceneEnvironment & sceneEnvironment,const ResMaterial material)290 MaterialState::ActivateFogParameters(const SceneEnvironment& sceneEnvironment, const ResMaterial material)
291 {
292 #if defined(NW_MATERIAL_PROFILE)
293     NW_PROFILE("MaterialState::ActivateFogParameters");
294 #endif
295 
296 #if defined(MATERIAL_SET_ENABLED)
297     u32 flags = material.GetFlags();
298 
299     enum
300     {
301         FOG_MODE_FALSE = 0,
302         FOG_MODE_FOG   = 5,
303         FOG_MODE_GAS   = 7,
304         REG_FOG_MODE   = 0xe0
305     };
306 
307     // フォグを設定します。
308     s32 fogMode = FOG_MODE_FALSE;
309     if (ut::CheckFlag(flags, ResMaterialData::FLAG_FOG_ENABLED))
310     {
311         if (sceneEnvironment.GetActiveFog() != NULL)
312         {
313             fogMode = FOG_MODE_FOG;
314         }
315     }
316 
317     {
318         const u32 HEADER_FOG_MODE = internal::MakeCommandHeader(REG_FOG_MODE, 1, false, 0x1);
319 
320         u32 FOG_COMMAND[] =
321         {
322             fogMode,
323             HEADER_FOG_MODE
324         };
325 
326         internal::NWUseCmdlist<sizeof(FOG_COMMAND)>(&FOG_COMMAND[0]);
327     }
328 #endif
329 }
330 
331 //----------------------------------------
332 NW_INLINE void
ActivateDepthOperation(const ResDepthOperation depthOperation)333 MaterialState::ActivateDepthOperation(const ResDepthOperation depthOperation)
334 {
335 #if defined(NW_MATERIAL_PROFILE)
336     NW_PROFILE("MaterialState::ActivateDepthOperation");
337 #endif
338 
339     GraphicsDevice::SetDepthTestEnabled(
340         ut::CheckFlag(
341             depthOperation.GetFlags(),
342             ResDepthOperationData::FLAG_TEST_ENABLED));
343 
344     GraphicsDevice::SetDepthMaskEnabled(
345         ut::CheckFlag(
346             depthOperation.GetFlags(),
347             ResDepthOperationData::FLAG_MASK_ENABLED));
348 
349     GraphicsDevice::ActivateMask();
350 
351     internal::NWUseCmdlist<sizeof(depthOperation.ref().m_CommandBuffer)>( &depthOperation.ref().m_CommandBuffer[0] );
352 }
353 
354 //----------------------------------------
355 NW_INLINE void
ActivateStencilOperation(const ResStencilOperation stencilOperation)356 MaterialState::ActivateStencilOperation(const ResStencilOperation stencilOperation)
357 {
358 #if defined(NW_MATERIAL_PROFILE)
359     NW_PROFILE("MaterialState::ActivateStencilOperation");
360 #endif
361 
362     if (!stencilOperation.IsValid())
363     {
364         return;
365     }
366 
367     if (stencilOperation.IsTestEnabled())
368     {
369         GraphicsDevice::SetStencilTestEnabled(true);
370     }
371     else
372     {
373         GraphicsDevice::SetStencilTestEnabled(false);
374     }
375     internal::NWUseCmdlist<sizeof(stencilOperation.ref().m_CommandBuffer)>( &stencilOperation.ref().m_CommandBuffer[0] );
376 }
377 
378 //----------------------------------------
379 NW_INLINE void
ActivateBlendOperation(const ResBlendOperation blendOperation)380 MaterialState::ActivateBlendOperation(const ResBlendOperation blendOperation)
381 {
382 #if defined(NW_MATERIAL_PROFILE)
383     NW_PROFILE("MaterialState::ActivateBlendOperation");
384 #endif
385 
386     ResBlendOperation::Mode mode = blendOperation.GetMode();
387 
388     if (mode == ResBlendOperation::MODE_NOT_USE)
389     {
390         GraphicsDevice::SetBlendEnabled(false);
391     }
392     else
393     {
394         GraphicsDevice::SetBlendEnabled(true);
395     }
396 
397     internal::NWUseCmdlist<sizeof(blendOperation.ref().m_CommandBuffer)>(blendOperation.ref().m_CommandBuffer);
398 }
399 
400 //----------------------------------------
401 NW_INLINE void
ActivateShaderParameter(const ShaderProgram * shaderProgram,const ResMaterial material)402 MaterialState::ActivateShaderParameter(
403         const ShaderProgram* shaderProgram,
404         const ResMaterial material)
405 {
406 #if defined(NW_MATERIAL_PROFILE)
407     NW_PROFILE("MaterialState::ActivateShaderParameter");
408 #endif
409 
410 #if defined(MATERIAL_SET_ENABLED)
411     ResShaderProgramDescription description = shaderProgram->GetActiveDescription();
412     ResShaderSymbolArray symbolArray = description.GetSymbols();
413     int symbolCount = description.GetSymbolsCount();
414 
415     // マテリアルのシェーダパラメータの値をすべて設定した後に、設定されていないパラメータに
416     // デフォルト値を設定します。
417 
418     bool symbolHasBeenSetFlag[64] = { false };
419 
420     ResShaderParameterArrayConst::const_iterator end = material.GetShaderParameters().end();
421     for ( ResShaderParameterArrayConst::const_iterator parameter = material.GetShaderParameters().begin();
422           parameter != end; ++parameter )
423     {
424         int symbolIndex = (*parameter).GetSymbolIndex();
425         if ( 0 <= symbolIndex && symbolIndex < symbolCount)
426         {
427             ResShaderSymbol shaderSymbol = symbolArray[symbolIndex];
428             if (shaderSymbol.IsEnabled() && shaderSymbol.GetLocation() >= 0)
429             {
430                 NW_ASSERT(shaderSymbol.GetLocation() < 96);
431 
432                 if (shaderSymbol.IsGeometryUniform())
433                 {
434                     shaderProgram->SetUserGeometryUniform(shaderSymbol.GetLocation(), (*parameter).GetParameter());
435                 }
436                 else
437                 {
438                     shaderProgram->SetUserVertexUniform(shaderSymbol.GetLocation(), (*parameter).GetParameter());
439                 }
440             }
441 
442             // シェーダシンボル自体が無効な場合にも、デフォルト値の設定は必要ないのでフラグは立てておく。
443             symbolHasBeenSetFlag[symbolIndex] = true;
444         }
445     }
446 
447     for (int symbolIndex = 0; symbolIndex < symbolCount; ++symbolIndex)
448     {
449         if ( ! symbolHasBeenSetFlag[symbolIndex] )
450         {
451             ResShaderSymbol shaderSymbol = symbolArray[symbolIndex];
452 
453             if (shaderSymbol.IsEnabled() && shaderSymbol.GetLocation() >= 0)
454             {
455                 NW_ASSERT(shaderSymbol.GetLocation() < 96);
456 
457                 if (shaderSymbol.IsGeometryUniform())
458                 {
459                     shaderProgram->SetUserGeometryUniform(shaderSymbol.GetLocation(), shaderSymbol.GetDefaultValue());
460                 }
461                 else
462                 {
463                     shaderProgram->SetUserVertexUniform(shaderSymbol.GetLocation(), shaderSymbol.GetDefaultValue());
464                 }
465             }
466         }
467     }
468 #endif
469 }
470 
471 //----------------------------------------
472 NW_INLINE void
ActivateFragmentLightParameters(const SceneEnvironment & sceneEnvironment,const ShaderProgram * shaderProgram,const ResMaterial material)473 MaterialState::ActivateFragmentLightParameters(
474     const SceneEnvironment& sceneEnvironment,
475     const ShaderProgram* shaderProgram,
476     const ResMaterial material)
477 {
478     // 各種ライトの ON/OFF を設定します。
479     enum
480     {
481         REG_FRAGMENT_LIGHT_ENABLED  = 0x1c6,
482         REG_FRAGMENT_LIGHT_ENABLED2 = 0x8F
483     };
484     const u32 ENABLED_HEADER  = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_ENABLED, 1, false, 0x1);
485     const u32 ENABLED_HEADER2 = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_ENABLED2, 1, false, 0x1);
486     bool isFragmentLightEnabled =
487         ut::CheckFlag(material.GetFlags(), ResMaterialData::FLAG_FRAGMENTLIGHT_ENABLED) &&
488         (sceneEnvironment.GetFragmentLightCount() != 0);
489 
490     u32 LIGHT_COUNT_COMMAND[] =
491     {
492         isFragmentLightEnabled ? 0 : 1,
493         ENABLED_HEADER,
494         isFragmentLightEnabled ? 1 : 0,
495         ENABLED_HEADER2
496     };
497 
498     // フラグメントライティングを行わない場合はクォータニオンの計算を省略します。
499     shaderProgram->SetVertexUniformBool(NW_GFX_VERTEX_UNIFORM(ISQUATE), isFragmentLightEnabled);
500 
501     internal::NWUseCmdlist<sizeof(LIGHT_COUNT_COMMAND)>( &LIGHT_COUNT_COMMAND[0] );
502 }
503 
504 //----------------------------------------
505 NW_INLINE void
ActivateShadingParameters(const SceneEnvironment & sceneEnvironment,const ShaderProgram * shaderProgram,const ResMaterial material)506 MaterialState::ActivateShadingParameters(
507     const SceneEnvironment& sceneEnvironment,
508     const ShaderProgram* shaderProgram,
509     const ResMaterial material)
510 {
511 #if defined(NW_MATERIAL_PROFILE)
512     NW_PROFILE("MaterialState::ActivateShadingParameters");
513 #endif
514 
515 #if defined(MATERIAL_SET_ENABLED)
516     u32 flags = material.GetFlags();
517 
518 #if defined(NW_GFX_VERTEX_LIGHT_ENABLED)
519     if (shaderProgram->GetActiveDescription().GetMaxVertexLightCount() > 0)
520     {
521         if (sceneEnvironment.GetVertexLightCount() > 0 &&
522             ut::CheckFlag(flags, ResMaterialData::FLAG_VERTEXLIGHT_ENABLED))
523         {
524             shaderProgram->SetVertexUniformBool(NW_GFX_VERTEX_UNIFORM(ISVERTL), true);
525         }
526         else
527         {
528             shaderProgram->SetVertexUniformBool(NW_GFX_VERTEX_UNIFORM(ISVERTL), false);
529         }
530     }
531 #endif
532 
533     if (ut::CheckFlag(
534         shaderProgram->GetActiveDescription().GetFlags(),
535         ResShaderProgramDescription::FLAG_IS_SUPPORTING_HEMISPHERE_LIGHTING))
536     {
537         if (sceneEnvironment.GetHemiSphereLight() != NULL &&
538             ut::CheckFlag(flags, ResMaterialData::FLAG_HEMISPHERELIGHT_ENABLED))
539         {
540             shaderProgram->SetVertexUniformBool(NW_GFX_VERTEX_UNIFORM(ISHEMIL), true);
541             shaderProgram->SetVertexUniformBool(
542                 NW_GFX_VERTEX_UNIFORM(ISHEMIO),
543                 ut::CheckFlag(flags, ResMaterialData::FLAG_HEMISPHERE_OCCLUSION_ENABLED));
544         }
545         else
546         {
547             shaderProgram->SetVertexUniformBool(NW_GFX_VERTEX_UNIFORM(ISHEMIL), false);
548         }
549     }
550 
551     enum
552     {
553         FOG_MODE_FALSE = 0,
554         FOG_MODE_FOG   = 5,
555         FOG_MODE_GAS   = 7,
556         REG_FOG_MODE   = 0xe0
557     };
558 
559     // フォグを設定します。
560     s32 fogMode = FOG_MODE_FALSE;
561     if (ut::CheckFlag(flags, ResMaterialData::FLAG_FOG_ENABLED))
562     {
563         if (sceneEnvironment.GetActiveFog() != NULL)
564         {
565             fogMode = FOG_MODE_FOG;
566         }
567     }
568 
569     {
570         const u32 HEADER_FOG_MODE = internal::MakeCommandHeader(REG_FOG_MODE, 1, false, 0x1);
571 
572         u32 FOG_COMMAND[] =
573         {
574             fogMode,
575             HEADER_FOG_MODE
576         };
577 
578         internal::NWUseCmdlist<sizeof(FOG_COMMAND)>(&FOG_COMMAND[0]);
579     }
580 #endif
581 }
582 
583 //----------------------------------------
584 NW_INLINE void
ActivateRasterization(const ResRasterization rasterization)585 MaterialState::ActivateRasterization(const ResRasterization rasterization)
586 {
587 #if defined(NW_MATERIAL_PROFILE)
588     NW_PROFILE("MaterialState::ActivateRasterization");
589 #endif
590 
591 #if defined(MATERIAL_SET_ENABLED)
592     NW_ASSERT(rasterization.IsValid());
593 
594     GraphicsDevice::SetPolygonOffsetEnabled(ut::CheckFlag(rasterization.GetFlags(), ResRasterizationData::FLAG_POLYGON_OFFSET_ENABLED));
595     GraphicsDevice::SetPolygonOffsetUnit(rasterization.GetPolygonOffsetUnit());
596     GraphicsDevice::ActivatePolygonOffset();
597 
598     // CullModeの設定
599     internal::NWUseCmdlist<sizeof(rasterization.ref().m_CommandBuffer)>( rasterization.ref().m_CommandBuffer );
600 #endif
601 }
602 
603 //----------------------------------------
604 NW_INLINE void
ActivateMaterialColor(const SceneEnvironment & sceneEnvironment,const ShaderProgram * shaderProgram,ResMaterialColor materialColor,bool useReflection)605 MaterialState::ActivateMaterialColor(
606     const SceneEnvironment& sceneEnvironment,
607     const ShaderProgram* shaderProgram,
608     ResMaterialColor materialColor,
609     bool useReflection)
610 {
611 #if defined(NW_MATERIAL_PROFILE)
612     NW_PROFILE("MaterialState::ActivateMaterialColor");
613 #endif
614 
615 #if defined(MATERIAL_SET_ENABLED)
616     NW_ASSERT(materialColor.IsValid());
617 
618     ResShaderProgramDescription resShaderProgram = shaderProgram->GetActiveDescription();
619 
620     // 頂点シェーダーにマテリアルカラーを設定します。
621     internal::NWSetVertexUniform4fv(VERTEX_SHADER_UNIFORM_MATDIFF_INDEX, 1, materialColor.GetDiffuse());
622     internal::NWSetVertexUniform4fv(VERTEX_SHADER_UNIFORM_MATAMBI_INDEX, 1, materialColor.GetAmbient());
623 
624     int lightCount = ut::Min(sceneEnvironment.GetFragmentLightCount(), MAX_PER_PIXEL_LIGHTS);
625     internal::ActivateFragmentLightCount( lightCount );
626 
627     internal::ActivateFragmentAmbientLight( materialColor, sceneEnvironment.GetAmbientLight() );
628 
629     for (int i = 0; i < lightCount; ++i)
630     {
631         const FragmentLight* light = sceneEnvironment.GetFragmentLight(i);
632 
633         internal::ActivateFragmentLight(i, materialColor, light, useReflection);
634     }
635 #endif
636 }
637 
638 //----------------------------------------
639 NW_INLINE void
ActivateFragmentLighting(const SceneEnvironment & sceneEnvironment,const ResFragmentLighting fragmentLighting)640 MaterialState::ActivateFragmentLighting(
641     const SceneEnvironment& sceneEnvironment,
642     const ResFragmentLighting fragmentLighting)
643 {
644 #if defined(NW_MATERIAL_PROFILE)
645     NW_PROFILE("MaterialState::ActivateFragmentLighting");
646 #endif
647 
648 #if defined(MATERIAL_SET_ENABLED)
649     NW_ASSERT(fragmentLighting.IsValid());
650 
651     // NOTE: リソース側であらかじめコマンドを持つようにできないかを検討。
652     //       fragmentLighting, fragmengShader(LayerConfig) のバッファを
653     //       それぞれ持っている部分が問題なので、計測してみて効果があるようなら
654     //       FragmentShaderクラス内でのメンバの引越しもあるかもしれない。
655     internal::ActivateFragmentLighting(fragmentLighting);
656 
657     bool geomFactor0 = ut::CheckFlag(
658             fragmentLighting.GetFlags(),
659             ResFragmentLightingData::FLAG_GEOMETRIC_FACTOR0_ENABLED);
660 
661     bool geomFactor1 = ut::CheckFlag(
662             fragmentLighting.GetFlags(),
663             ResFragmentLightingData::FLAG_GEOMETRIC_FACTOR1_ENABLED);
664 
665     int lightCount = sceneEnvironment.GetFragmentLightCount();
666     for (int i = 0; i < lightCount; ++i)
667     {
668         const FragmentLight* light = sceneEnvironment.GetFragmentLight(i);
669         ResFragmentLight resLight = light->GetResFragmentLight();
670         s32 lightKind = resLight.GetLightKind();
671 
672         bool twoSideDiffuse = ut::CheckFlag(resLight.GetFlags(), ResFragmentLightData::FLAG_TWO_SIDE_DIFFUSE_ENABLED);
673         bool isDirectional = (lightKind == ResFragmentLight::KIND_DIRECTIONAL) || GraphicsDevice::GetFragmentLightPositionW(i);
674 
675         internal::ActivateFragmentLightParameters(i, isDirectional, twoSideDiffuse, geomFactor0, geomFactor1);
676     }
677 #endif
678 }
679 
680 //----------------------------------------
681 NW_INLINE void
ActivateTextureMappers(const ResMaterial texMapperMaterial)682 MaterialState::ActivateTextureMappers(const ResMaterial texMapperMaterial)
683 {
684 #if defined(NW_MATERIAL_PROFILE)
685     NW_PROFILE("MaterialState::ActivateTextureMappers");
686 #endif
687 
688 #if defined(MATERIAL_SET_ENABLED)
689     // TODO: プロシージャルテクスチャには未対応
690     u32 samplerSetting = 0;
691 
692     for ( s32 textureUnit = 0; textureUnit < texMapperMaterial.GetTextureMappersCount(); textureUnit++)
693     {
694         const ResTextureMapper textureMapper = texMapperMaterial.GetTextureMappers(textureUnit);
695         if ( ! textureMapper.IsValid() )
696         {
697             continue;
698         }
699 
700         samplerSetting |= 1 << textureUnit;
701 
702         // TODO: ShadowTextureMapperには未対応。
703         const ResPixelBasedTextureMapper pixTexMapper = ResStaticCast<const ResPixelBasedTextureMapper>(textureMapper);
704 
705         // 0x81-0x8a, 0x8e[3:0] の内容はここに含まれる
706         const u32* command = pixTexMapper.GetCommandCache();
707         u32  commandSize   = pixTexMapper.GetCommandSizeToSend();
708 
709         internal::NWUseCmdlist(command, commandSize);
710     }
711 
712     const u32 HEADER = internal::MakeCommandHeader(PICA_REG_TEXTURE_FUNC, 1, false, 0x5);
713 
714     u32 INVALIDATE_TEXTURE_CACHE[] =
715     {
716         samplerSetting | 0x00010000,
717         HEADER
718     };
719 
720     internal::NWUseCmdlist<sizeof(INVALIDATE_TEXTURE_CACHE)>(&INVALIDATE_TEXTURE_CACHE[0]);
721 #endif
722 }
723 
724 
725 //----------------------------------------
726 NW_INLINE void
ActivateParticleTextureMappers(const ResMaterial texMapperMaterial)727 MaterialState::ActivateParticleTextureMappers(const ResMaterial texMapperMaterial)
728 {
729 #if defined(NW_MATERIAL_PROFILE)
730     NW_PROFILE("MaterialState::ActivateParticleTextureMappers");
731 #endif
732 
733 #if defined(MATERIAL_SET_ENABLED)
734     // TODO: プロシージャルテクスチャには未対応
735     const ResTextureMapper textureMapper = texMapperMaterial.GetTextureMappers(0);
736     if ( textureMapper.IsValid() )
737     {
738         // TODO: ShadowTextureMapperには未対応。
739         const ResPixelBasedTextureMapper pixTexMapper = ResStaticCast<const ResPixelBasedTextureMapper>(textureMapper);
740 
741         // 0x81-0x8a, 0x8e[3:0] の内容はここに含まれる
742         const u32* command = pixTexMapper.GetCommandCache();
743         u32  commandSize   = pixTexMapper.GetCommandSizeToSend();
744 
745         internal::NWUseCmdlist(command, commandSize);
746     }
747 
748     const u32 HEADER = internal::MakeCommandHeader(PICA_REG_TEXTURE_FUNC, 1, false, 0x5);
749 
750     const u32 INVALIDATE_TEXTURE_CACHE[] =
751     {
752         0x00010001,
753         HEADER
754     };
755     internal::NWUseCmdlist<sizeof(INVALIDATE_TEXTURE_CACHE)>(&INVALIDATE_TEXTURE_CACHE[0]);
756 #endif
757 }
758 
759 
760 //----------------------------------------
761 NW_INLINE void
ActivateProceduralTextureMapper(RenderContext * renderContext,const ShaderProgram * shaderProgram,const ResMaterial material)762 MaterialState::ActivateProceduralTextureMapper(
763     RenderContext* renderContext,
764     const ShaderProgram* shaderProgram,
765     const ResMaterial material)
766 {
767 
768 #if defined(NW_MATERIAL_PROFILE)
769     NW_PROFILE("MaterialState::ActivateProceduralTextureMapper");
770 #endif
771     NW_UNUSED_VARIABLE(renderContext);
772     NW_UNUSED_VARIABLE(shaderProgram);
773     NW_UNUSED_VARIABLE(material);
774 }
775 
776 //----------------------------------------
777 NW_INLINE void
ActivateTextureCombiners(const ResFragmentShader fragmentShader,const ResMaterialColor materialColor)778 MaterialState::ActivateTextureCombiners(
779     const ResFragmentShader fragmentShader,
780     const ResMaterialColor materialColor)
781 {
782 #if defined(NW_MATERIAL_PROFILE)
783     NW_PROFILE("MaterialState::ActivateTextureCombiners");
784 #endif
785 
786 #if defined(MATERIAL_SET_ENABLED)
787 #ifdef NW_TARGET_CTR_GL_FINAL
788     internal::NWUseCmdlist<sizeof(fragmentShader.ref().m_BufferCommand)>(&(fragmentShader.ref().m_BufferCommand[0]));
789 #endif
790 
791     for (uint stage = 0; stage < COMBINER_AVAILABLE_COUNT; stage++)
792     {
793         ResTextureCombiner textureCombiner = fragmentShader.GetTextureCombiners(stage);
794 
795         // 計測してみたところ、現状では処理のオーバーヘッドによる有意な差が見られなかったので、
796         // コンスタントカラーはマテリアルカラーから参照する形にしておく。
797         u32 constantU32 = GetConstantColorU32(
798             textureCombiner.GetConstant(),
799             materialColor);
800 
801         textureCombiner.SetConstantCmd( constantU32 );
802 
803         internal::NWUseCmdlist<sizeof(textureCombiner.ref().m_CommandBuffer)>( reinterpret_cast<const u32*>(textureCombiner.ref().m_CommandBuffer) );
804     }
805 #endif
806 }
807 
808 //----------------------------------------
809 NW_INLINE void
ActivateAlphaTest(const ResAlphaTest alphaTest)810 MaterialState::ActivateAlphaTest(const ResAlphaTest alphaTest)
811 {
812 #if defined(NW_MATERIAL_PROFILE)
813     NW_PROFILE("MaterialState::ActivateAlphaTest");
814 #endif
815 
816 #if defined(MATERIAL_SET_ENABLED)
817     NW_ASSERT(alphaTest.IsValid());
818     internal::NWUseCmdlist<sizeof(alphaTest.ref().m_CommandBuffer)>( &alphaTest.ref().m_CommandBuffer[0] );
819 #endif
820 }
821 
822 //----------------------------------------
823 NW_INLINE void
ActivateFragmentOperation(const ResFragmentOperation fragmentOperation)824 MaterialState::ActivateFragmentOperation(const ResFragmentOperation fragmentOperation)
825 {
826 #if defined(MATERIAL_SET_ENABLED)
827     ResDepthOperation resDepthOperation = fragmentOperation.GetDepthOperation();
828     ResStencilOperation resStencilOperation = fragmentOperation.GetStencilOperation();
829     ResBlendOperation resBlendOperation = fragmentOperation.GetBlendOperation();
830 
831     ActivateDepthOperation(resDepthOperation);
832     ActivateStencilOperation(resStencilOperation);
833     ActivateBlendOperation(resBlendOperation);
834 
835     GraphicsDevice::SetFragmentOperationMode(fragmentOperation.GetFragmentOperationMode());
836     GraphicsDevice::ActivateFrameBuffer();
837 #endif
838 }
839 
840 } // namespace internal
841 } // namespace gfx
842 } // namespace nw
843 
844 #endif // NW_GFX_MATERIALSTATE_H_
845