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