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