1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_ActivateCommand.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_ACTIVATE_COMMAND_H_
19 #define NW_GFX_ACTIVATE_COMMAND_H_
20
21 #include <nw/types.h>
22
23
24 #include <gles2/gl2.h>
25 #include <gles2/gl2ext.h>
26 #include <nn/gx.h>
27
28 #include <nw/gfx/gfx_CommandUtil.h>
29 #include <nw/gfx/gfx_FragmentLight.h>
30 #include <nw/gfx/gfx_AmbientLight.h>
31 #include <nw/gfx/res/gfx_ResMaterial.h>
32 #include <nw/gfx/res/gfx_ResParticleShape.h>
33
34 namespace nw {
35 namespace gfx {
36
37 class ShaderProgram;
38
39 namespace internal {
40
41 class CommandCacheHelper
42 {
43 public:
44
45 //--------------------------------------------------------------------------
46 //! @brief U32 で表されたカラーを掛けます。
47 //!
48 //! @param[in] lhs 乗算を行う U32 カラー値です。
49 //! @param[in] rhs 乗算を行う U32 カラー値です。
50 //!
51 //! @return 乗算後の値を返します。
52 //---------------------------------------------------------------------------
MultU32Color(u32 lhs,u32 rhs)53 static NW_INLINE u32 MultU32Color(u32 lhs, u32 rhs)
54 {
55 const u32 MASKx2 = (0xff << 1);
56
57 u32 r = ((((lhs << 1) & MASKx2) + 1) * (((rhs << 1) & MASKx2) + 1)) >> 10;
58 u32 g = ((((lhs >> 7) & MASKx2) + 1) * (((rhs >> 7) & MASKx2) + 1)) >> 10;
59 u32 b = ((((lhs >> 15) & MASKx2) + 1) * (((rhs >> 15) & MASKx2) + 1)) >> 10;
60
61 return (r << 20) | (g << 10) | b;
62 }
63
64 //--------------------------------------------------------------------------
65 //! @brief U32 で表されたカラーを掛けた後に加算を行います。
66 //!
67 //! @param[in] lhs 乗算を行う U32 カラー値です。
68 //! @param[in] rhs 乗算を行う U32 カラー値です。
69 //! @param[in] add 加算を行う U32 カラー値です。
70 //!
71 //! @return 乗算後の値を返します。
72 //---------------------------------------------------------------------------
MultAddU32Color(u32 lhs,u32 rhs,u32 add)73 static NW_INLINE u32 MultAddU32Color(u32 lhs, u32 rhs, u32 add)
74 {
75 const u32 MASK = 0xff;
76 const u32 MASKx2 = (0xff << 1);
77
78 u32 r = (((((lhs << 1) & MASKx2) + 1) * (((rhs << 1) & MASKx2) + 1)) >> 10) + (add & MASK);
79 u32 g = (((((lhs >> 7) & MASKx2) + 1) * (((rhs >> 7) & MASKx2) + 1)) >> 10) + ((add >> 8) & MASK);
80 u32 b = (((((lhs >> 15) & MASKx2) + 1) * (((rhs >> 15) & MASKx2) + 1)) >> 10) + ((add >> 16) & MASK);
81
82 return (ut::Clamp<u32>(r, 0, 255) << 20) | (ut::Clamp<u32>(g, 0, 255) << 10) | ut::Clamp<u32>(b, 0, 255);
83 }
84
85 //--------------------------------------------------------------------------
86 //! @brief 頂点ストリームの型と要素数から、HWの頂点フォーマット設定を取得します。
87 //!
88 //! @param[in] dimension 頂点属性の要素数です。
89 //! @param[in] format 頂点属性のフォーマットです。
90 //!
91 //! @return ハードに設定する頂点フォーマット定数を返します。
92 //---------------------------------------------------------------------------
GetVertexFormat(s32 dimension,GLuint format)93 static NW_INLINE u32 GetVertexFormat(s32 dimension, GLuint format)
94 {
95 u32 result = 0;
96
97 switch ( format )
98 {
99 case GL_BYTE: result = 0; break;
100 case GL_UNSIGNED_BYTE: result = 1; break;
101 case GL_SHORT: result = 2; break;
102 case GL_FLOAT: result = 3; break;
103 default: NW_FATAL_ERROR("unknown format");
104 }
105
106 return result + ((dimension - 1) << 2);
107 }
108
109 //--------------------------------------------------------------------------
110 //! @brief 頂点ストリームの型と要素数から、頂点サイズを取得します。
111 //!
112 //! @param[in] dimension 頂点属性の要素数です。
113 //! @param[in] format 頂点属性のフォーマットです。
114 //!
115 //! @return ハードに設定する頂点サイズを返します。
116 //---------------------------------------------------------------------------
GetVertexSize(s32 dimension,GLuint format)117 static NW_INLINE u32 GetVertexSize(s32 dimension, GLuint format)
118 {
119 u32 result = 0;
120
121 switch ( format )
122 {
123 case GL_BYTE: return dimension;
124 case GL_UNSIGNED_BYTE: return dimension;
125 case GL_SHORT: return dimension * 2;
126 case GL_FLOAT: return dimension * 4;
127 default: NW_FATAL_ERROR("unknown format");
128 }
129
130 return 0;
131 }
132 };
133
134
135
136 //--------------------------------------------------------------------------
137 //! @brief フラグメントライト数を設定します。
138 //!
139 //! @param[in] count 有効なライトの数です。
140 //---------------------------------------------------------------------------
141 NW_INLINE void
ActivateFragmentLightCount(s32 count)142 ActivateFragmentLightCount(s32 count)
143 {
144 enum
145 {
146 REG_FRAGMENT_LIGHT_COUNT = 0x1c2,
147 REG_FRAGMENT_LIGHT_MASK = 0x1d9
148 };
149
150 const u32 COUNT_HEADER = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_COUNT, 1, false, 0x1);
151 const u32 LIGHT_MASK_HEADER = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_MASK, 1, false, 0xF);
152
153 u32 LIGHT_COUNT_COMMAND[] =
154 {
155 0,
156 COUNT_HEADER
157 #if defined(NW_TARGET_CTR_GL_FINAL)
158 ,0,
159 LIGHT_MASK_HEADER
160 #endif
161 };
162
163 LIGHT_COUNT_COMMAND[0] = (count > 0) ? count - 1 : 0;
164
165 #if defined(NW_TARGET_CTR_GL_FINAL)
166 for (int i = 0; i < count; ++i)
167 {
168 LIGHT_COUNT_COMMAND[2] |= i << (4 * i);
169 }
170 #endif
171
172 internal::NWUseCmdlist<sizeof(LIGHT_COUNT_COMMAND)>( &LIGHT_COUNT_COMMAND[0] );
173 }
174
175 //--------------------------------------------------------------------------
176 //! @brief フラグメントライトレジスタの設定をおこないます。
177 //!
178 //! @param[in] index ライトを設定するインデックス番号です。
179 //! @param[in] materialColor マテリアルカラーです。
180 //! @param[in] light フラグメントライトセットです。
181 //! @param[in] useReflection 反射テーブルが有効かどうかを表すフラグです。
182 //---------------------------------------------------------------------------
183 NW_INLINE void
ActivateFragmentLight(s32 index,ResMaterialColor materialColor,const FragmentLight * light,bool useReflection)184 ActivateFragmentLight(s32 index, ResMaterialColor materialColor, const FragmentLight* light, bool useReflection)
185 {
186 enum { REG_FRAGMENT_COLOR_BASE = 0x140 };
187
188 const u32 HEADER = internal::MakeCommandHeader(REG_FRAGMENT_COLOR_BASE, 4, true, 0xF);
189
190 NW_NULL_ASSERT( light );
191
192 ResFragmentLight resLight = light->GetResFragmentLight();
193
194 u32 specular0U32 = CommandCacheHelper::MultU32Color(resLight.GetSpecular0U32(), materialColor.GetSpecular0U32());
195 u32 diffuseU32 = CommandCacheHelper::MultU32Color(resLight.GetDiffuseU32(), materialColor.GetDiffuseU32());
196 u32 ambientU32 = CommandCacheHelper::MultU32Color(resLight.GetAmbientU32(), materialColor.GetAmbientU32());
197 u32 specular1U32 = resLight.GetSpecular1U32();
198
199 if (useReflection)
200 {
201 const u32 MASK = 0xff;
202 u8 r = (specular1U32 & MASK);
203 u8 g = ((specular1U32 >> 8) & MASK);
204 u8 b = ((specular1U32 >> 16) & MASK);
205 specular1U32 = (static_cast<u32>(r) << 20) | (static_cast<u32>(g) << 10) | (static_cast<u32>(b));
206 }
207 else
208 {
209 specular1U32 = CommandCacheHelper::MultU32Color(resLight.GetSpecular1U32(), materialColor.GetSpecular1U32());
210 }
211
212 u32 LIGHT_COMMAND[6] =
213 {
214 specular0U32,
215 HEADER + (0x10 * index),
216 specular1U32,
217 diffuseU32,
218 ambientU32,
219 0 // padding
220 };
221
222 internal::NWUseCmdlist<sizeof(LIGHT_COMMAND)>( &LIGHT_COMMAND[0] );
223 }
224
225 //--------------------------------------------------------------------------
226 //! @brief アンビエントライト用のコマンドを設定します。
227 //!
228 //! @param[in] materialColor マテリアルカラーの情報です。
229 //! @param[in] light アンビエントライトの情報です。
230 //---------------------------------------------------------------------------
231 NW_INLINE void
ActivateFragmentAmbientLight(ResMaterialColor materialColor,const AmbientLight * light)232 ActivateFragmentAmbientLight(ResMaterialColor materialColor, const AmbientLight* light)
233 {
234 enum { REG_FRAGMENT_COLOR_AMBIENT = 0x1c0 };
235
236 u32 ambientU32 = 0x0;
237 const u32 HEADER = internal::MakeCommandHeader(REG_FRAGMENT_COLOR_AMBIENT, 1, false, 0xF);
238
239 if (light)
240 {
241 ResAmbientLight resLight = light->GetResAmbientLight();
242 ambientU32 = CommandCacheHelper::MultAddU32Color(resLight.GetAmbientU32(), materialColor.GetAmbientU32(), materialColor.GetEmissionU32());
243 }
244 else
245 {
246 u32 emissionU32 = materialColor.GetEmissionU32();
247 const u32 MASK = 0xff;
248 u8 r = (emissionU32 & MASK);
249 u8 g = ((emissionU32 >> 8) & MASK);
250 u8 b = ((emissionU32 >> 16) & MASK);
251 ambientU32 = (static_cast<u32>(r) << 20) | (static_cast<u32>(g) << 10) | (static_cast<u32>(b));
252 }
253
254 u32 LIGHT_COMMAND[2] =
255 {
256 ambientU32,
257 HEADER
258 };
259
260 internal::NWUseCmdlist<sizeof(LIGHT_COMMAND)>( &LIGHT_COMMAND[0] );
261 }
262
263 //--------------------------------------------------------------------------
264 //! @brief フラグメントライトのパラメータを設定します。
265 //!
266 //! @param[in] index ライトのインデックスを設定します。
267 //! @param[in] isDirectional ディレクショナルライトかどうかのフラグです。
268 //! @param[in] twoSided 2 sided ライティングのフラグです。
269 //! @param[in] geomFactor0 ジオメトリックファクタ0を使用するかどうかのフラグです。
270 //! @param[in] geomFactor1 ジオメトリックファクタ1を使用するかどうかのフラグです。
271 //---------------------------------------------------------------------------
272 NW_INLINE void
ActivateFragmentLightParameters(s32 index,bool isDirectional,bool twoSided,bool geomFactor0,bool geomFactor1)273 ActivateFragmentLightParameters(s32 index, bool isDirectional, bool twoSided, bool geomFactor0, bool geomFactor1)
274 {
275 enum
276 {
277 REG_FRAGMENT_LIGHT_TYPE = 0x149
278 };
279
280 const u32 HEADER = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_TYPE, 1, false, 0x1);
281
282 u32 LIGHT_COMMAND[2] =
283 {
284 0,
285 HEADER + 0x10 * index
286 };
287
288 if (isDirectional)
289 {
290 LIGHT_COMMAND[0] |= 0x1;
291 }
292
293 if (twoSided)
294 {
295 LIGHT_COMMAND[0] |= 0x2;
296 }
297
298 if (geomFactor0)
299 {
300 LIGHT_COMMAND[0] |= 0x4;
301 }
302
303 if (geomFactor1)
304 {
305 LIGHT_COMMAND[0] |= 0x8;
306 }
307
308 internal::NWUseCmdlist<sizeof(LIGHT_COMMAND)>( &LIGHT_COMMAND[0] );
309 }
310
311 //--------------------------------------------------------------------------
312 //! @brief フラグメントライティングの設定をおこないます。
313 //!
314 //! @param[in] fragmentLighting フラグメントライティング設定です。
315 //---------------------------------------------------------------------------
316 NW_INLINE void
ActivateFragmentLighting(const ResFragmentLighting fragmentLighting)317 ActivateFragmentLighting(const ResFragmentLighting fragmentLighting)
318 {
319 const u32 REG_LIGHT_ENV = 0x1c3;
320 const u32 REG_LIGHT_ENV2 = 0x1c4;
321
322 const u32 HEADER = internal::MakeCommandHeader(REG_LIGHT_ENV, 1, false, 0xf);
323 const u32 HEADER2 = internal::MakeCommandHeader(REG_LIGHT_ENV2, 1, false, 0x4);
324
325 u32 LIGHT_COMMAND[4] =
326 {
327 0,
328 HEADER,
329 0,
330 HEADER2
331 };
332
333 // TODO: Shadow には未対応。
334
335 // 0x1c3 LightEnv.FUNC_MODE1のマッピング
336 // shadowEnable [0]
337 // fresnelSelector[3:2]
338 // layerConfig [7:4]
339 // shadowPrimary [16]
340 // shadowSecondary[17]
341 // invertShadow [18]
342 // shadowAlpha [19]
343 // bumpSelector [23:22]
344 // shadowSelector [25:24]
345 // clampHighlights[27]
346 // bumpMode [29:28]
347 // bumpRenorm [30]
348 // 必ず1を設定 [31]
349 // tex0 remapping [9:8] 0 としておけば問題ない。
350 // tex1 remapping [11:10] 1としておけば問題ない
351
352 u32 layerConfig = fragmentLighting.GetLayerConfig();
353 u32 fresnelSelector = fragmentLighting.GetFresnelConfig();
354 u32 bumpSelector = fragmentLighting.GetBumpTextureIndex();
355 u32 bumpMode = fragmentLighting.GetBumpMode();
356 // bumpMode が BUMP_NOT_USED の場合と bumpRenorm が true の場合に 0に設定する。
357 bool bumpRenorm = fragmentLighting.IsBumpRenormalize() || (bumpMode == 0);
358 bool clampHighlights = ut::CheckFlag(fragmentLighting.GetFlags(), ResFragmentLightingData::FLAG_CLAMP_HIGH_LIGHT);
359
360 LIGHT_COMMAND[0] = fresnelSelector << 2 |
361 layerConfig << 4 |
362 bumpSelector << 22 |
363 (clampHighlights ? 1 : 0) << 27 |
364 bumpMode << 28 |
365 0x1u << 10 |
366 (bumpRenorm ? 0 : 1) << 30 |
367 0x1u << 31;
368
369 // 0x1c4 LightEnv.FUNC_MODE2のマッピング
370 // sourceShadowed [7:0]
371 // lutEnabledD0 [16]
372 // lutEnabledD1 [17]
373 // lutEnabledSP [18] 常に1
374 // fresnelSelector [19] GL_LIGHT_ENV_NO_FRESNEL_DMP の場合1
375 // lutEnabledRefl [22:20]
376 // spotEnabled [15:8] TSのみの設定。
377 // distanceAttnEnabled [31:24] TSのみの設定。
378
379 bool lutEnabledD0 = ut::CheckFlag(fragmentLighting.GetFlags(), ResFragmentLightingData::FLAG_DISTRIBUTION0_ENABLED);
380 bool lutEnabledD1 = ut::CheckFlag(fragmentLighting.GetFlags(), ResFragmentLightingData::FLAG_DISTRIBUTION1_ENABLED);
381 bool lutEnabledRefl = ut::CheckFlag(fragmentLighting.GetFlags(), ResFragmentLightingData::FLAG_REFLECTION_ENABLED);
382
383 LIGHT_COMMAND[2] = (lutEnabledD0 ? 0 : 1) << 16 |
384 (lutEnabledD1 ? 0 : 1) << 17 |
385 1 << 18 |
386 ((fresnelSelector == 0) ? 1 : 0) << 19 |
387 ((lutEnabledRefl ? 0 : 7) << 20);
388
389 internal::NWUseCmdlist<sizeof(LIGHT_COMMAND)>( &LIGHT_COMMAND[0] );
390 }
391
392 //--------------------------------------------------------------------------
393 //! @brief 頂点属性の設定をクリアします。
394 //---------------------------------------------------------------------------
395 void ClearVertexAttribute();
396
397 //--------------------------------------------------------------------------
398 //! @brief 頂点属性の設定をおこないます。
399 //!
400 //! @param[in] shape シェイプクラスです。
401 //! @param[in] shaderProgramDesc シェーダープログラムの詳細設定を表すバイナリリソースクラスです。
402 //!
403 //! @return 生成したコマンドのサイズです。
404 //---------------------------------------------------------------------------
405 s32 SetupVertexAttributeCommand(
406 CommandBufferInfo& bufferInfo,
407 ResSeparateDataShape shape,
408 ResShaderProgramDescription shaderProgramDesc );
409
410 s32 SetupVertexAttributeCommand(
411 CommandBufferInfo& bufferInfo,
412 ResParticleShape shape,
413 ResShaderProgramDescription shaderProgramDesc );
414
415 //--------------------------------------------------------------------------
416 //! @brief 頂点属性の非アクティブ化設定をおこないます。
417 //!
418 //! @param[in] shape シェイプクラスです。
419 //! @param[in] shaderProgramDesc シェーダープログラムの詳細設定を表すバイナリリソースクラスです。
420 //!
421 //! @return 生成したコマンドのサイズです。
422 //---------------------------------------------------------------------------
423 s32 SetupDeactivateVertexAttributeCommand(
424 CommandBufferInfo& bufferInfo,
425 ResSeparateDataShape shape,
426 ResShaderProgramDescription shaderProgramDesc );
427
428 s32 SetupDeactivateVertexAttributeCommand(
429 CommandBufferInfo& bufferInfo,
430 ResParticleShape shape,
431 ResShaderProgramDescription shaderProgramDesc );
432
433
434 //--------------------------------------------------------------------------
435 //! @brief シェーダモードの設定をおこないます。
436 //!
437 //! @param[in] useGeometry ジオメトリシェーダの有無です。
438 //!
439 //! @return 生成したコマンドのサイズです。
440 //---------------------------------------------------------------------------
441 s32 SetupShaderProgramMode(bool useGeometry);
442
443 //--------------------------------------------------------------------------
444 //! @brief インデックスストリーム単位の DrawElements のコマンドを生成します。
445 //!
446 //! @param[in] shaderProgramDescription シェーダープログラムの詳細設定を表すバイナリリソースクラスです。
447 //! @param[in] indexStream 頂点ストリームによる頂点属性を表すバイナリリソースクラスです。
448 //!
449 //! @return 生成したコマンドのサイズです。
450 //---------------------------------------------------------------------------
451 s32 SetupDrawIndexStreamCommand(
452 CommandBufferInfo& bufferInfo,
453 ResIndexStream indexStream,
454 bool hasGeometryShader );
455
456 //---------------------------------------------------------------------------
457 //! @brief インデックスストリーム単位の DrawElements のコマンドサイズを計算します。
458 //!
459 //! @param[in] indexStream 頂点ストリームによる頂点属性を表すバイナリリソースクラスです。
460 //!
461 //! @return コマンドのサイズです。
462 //---------------------------------------------------------------------------
463 s32 CalcSetupDrawIndexStreamCommand( ResIndexStream indexStream );
464
465
466 //---------------------------------------------------------------------------
467 //! @brief 頂点属性セットアップ用コマンドのコマンドサイズを計算します。
468 //! SeparateDataShape 用です。
469 //!
470 //! @param[in] shape 対象となるシェイプです。
471 //! @param[in] shaderProgramDesc 使用するシェーダプログラムです。
472 //!
473 //! @return コマンドのサイズです。
474 //---------------------------------------------------------------------------
475 s32 CalcSetupActivateVertexAttributeCommandSize(
476 ResSeparateDataShape shape,
477 ResShaderProgramDescription shaderProgramDesc );
478
479 //---------------------------------------------------------------------------
480 //! @brief 頂点属性セットアップ用コマンドのコマンドサイズを計算します。
481 //! ResParticleShape 用です。
482 //!
483 //! @param[in] shape 対象となるシェイプです。
484 //! @param[in] shaderProgramDesc 使用するシェーダプログラムです。
485 //!
486 //! @return コマンドのサイズです。
487 //---------------------------------------------------------------------------
488 s32 CalcSetupActivateVertexAttributeCommandSize(
489 ResParticleShape shape,
490 ResShaderProgramDescription shaderProgramDesc );
491
492 //---------------------------------------------------------------------------
493 //! @brief 頂点属性無効化用コマンドのコマンドサイズを計算します。
494 //! SeparateDataShape 用です。
495 //!
496 //! @param[in] shape 対象となるシェイプです。
497 //! @param[in] shaderProgramDesc 使用するシェーダプログラムです。
498 //!
499 //! @return コマンドのサイズです。
500 //---------------------------------------------------------------------------
501 s32 CalcSetupDeactivateVertexAttributeCommandSize(
502 ResSeparateDataShape shape,
503 ResShaderProgramDescription shaderProgramDesc );
504
505 //---------------------------------------------------------------------------
506 //! @brief 頂点属性無効化用コマンドのコマンドサイズを計算します。
507 //! ResParticleShape 用です。
508 //!
509 //! @param[in] shape 対象となるシェイプです。
510 //! @param[in] shaderProgramDesc 使用するシェーダプログラムです。
511 //!
512 //! @return コマンドのサイズです。
513 //---------------------------------------------------------------------------
514 s32 CalcSetupDeactivateVertexAttributeCommandSize(
515 ResParticleShape shape,
516 ResShaderProgramDescription shaderProgramDesc );
517
518
519
520 } // namespace internal
521 } // namespace gfx
522 } // namespace nw
523
524
525 #endif // NW_GFX_ACTIVATE_COMMAND_H_
526