1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gr_FragmentLight.cpp
4 
5   Copyright (C)2010 Nintendo Co., Ltd.  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   $Rev: 26237 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/gr/CTR/gr_FragmentLight.h>
17 
18 namespace nn
19 {
20     namespace gr
21     {
22         namespace CTR
23         {
24 
MakeCommand(u32 * command) const25             u32* FragmentLight::Source::MakeCommand( u32* command ) const
26             {
27                 u32 reg = PICA_REG_FRAG_LIGHT_START + id * PICA_FRAG_LIGHT_STRIDE;
28 
29                 *command++ = specular0B | specular0G << 10 | specular0R << 20;     // specular0
30                 *command++ = PICA_CMD_HEADER_BURSTSEQ( reg, 12 );                   // header
31                 *command++ = specular1B | specular1G << 10 | specular1R << 20;     // specular1
32                 *command++ = diffuseB   | diffuseG   << 10 | diffuseR   << 20;     // diffuse
33                 *command++ = ambientB   | ambientG   << 10 | ambientR   << 20;     // ambient
34                 *command++ = posXY;
35                 *command++ = posZ;
36                 *command++ = spotDirectionXY;
37                 *command++ = spotDirectionZ;
38                 *command++ = 0;
39                 *command++ = isInfinity | ( isEnableTwoSideDiffuse ? 1 : 0 ) << 1 |
40                           ( isEnableGeomFactor0 ? 1 : 0 ) << 2 | ( isEnableGeomFactor1 ? 1 : 0 ) << 3;
41                 *command++ = distAttnBias;
42                 *command++ = distAttnScale;
43                 *command++ = 0;
44 
45                 return command;
46             }
47 
48             //------------------------------------------------------------------------------
49 
Source()50             FragmentLight::Source::Source()
51                 : id( 0 ),
52                   isEnableTwoSideDiffuse( false ),
53                   isEnableGeomFactor0( false ),
54                   isEnableGeomFactor1( false ),
55                   diffuseR( 255 ),
56                   diffuseG( 255 ),
57                   diffuseB( 255 ),
58                   ambientR(   0 ),
59                   ambientG(   0 ),
60                   ambientB(   0 ),
61                   specular0R( 255 ),
62                   specular0G( 255 ),
63                   specular0B( 255 ),
64                   specular1R( 255 ),
65                   specular1G( 255 ),
66                   specular1B( 255 ),
67                   posXY( 0 ),
68                   posZ( 0 ),
69                   isInfinity( 0 ),
70                   distAttnBias( 0 ),
71                   distAttnScale( 0 ),
72                   spotDirectionXY( 0 ),
73                   spotDirectionZ( 0 )
74             {
75             }
76 
77             //------------------------------------------------------------------------------
78 
MakeLutConfigCommand(u32 * command) const79             u32* FragmentLight::MakeLutConfigCommand( u32* command ) const
80             {
81                 // 0x1d0
82                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_ABSLUTINPUT(
83                     lutConfigD0.isAbs,
84                     lutConfigD1.isAbs,
85                     lutConfigSP.isAbs,
86                     lutConfigFR.isAbs,
87                     lutConfigRB.isAbs,
88                     lutConfigRG.isAbs,
89                     lutConfigRR.isAbs );
90                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_ABSLUTINPUT );
91 
92                 // 0x1d1
93                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_LUTINPUT(
94                     lutConfigD0.input,
95                     lutConfigD1.input,
96                     lutConfigSP.input,
97                     lutConfigFR.input,
98                     lutConfigRB.input,
99                     lutConfigRG.input,
100                     lutConfigRR.input );
101                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_LUTINPUT );
102 
103                 // 0x1d2
104                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_LUTSCALE(
105                     lutConfigD0.scale,
106                     lutConfigD1.scale,
107                     lutConfigSP.scale,
108                     lutConfigFR.scale,
109                     lutConfigRB.scale,
110                     lutConfigRG.scale,
111                     lutConfigRR.scale );
112                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_LUTSCALE );
113 
114                 return command;
115             }
116 
117             //------------------------------------------------------------------------------
118 
MakeLightEnvCommand(u32 * command) const119             u32* FragmentLight::MakeLightEnvCommand( u32* command ) const
120             {
121                 u32 regLightEnable     = 0xff00ffff;
122                 u32 regLightEnableEach = 0;
123                 s32 count = 0;
124 
125                 regLightEnable |= PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE1_LUT(
126                     isEnableLutD0,
127                     isEnableLutD1,
128                     fresnelSelector,
129                     isEnableLutRef1 );
130 
131                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
132                 {
133                     if ( isEnable[ i ] == false ) continue;
134 
135                     if ( isShadowed[ i ] )
136                     {
137                         regLightEnable &= ~( i << i );
138                     }
139 
140                     if ( isEnableSpot[ i ] )
141                     {
142                         regLightEnable &= ~( 1 << ( 8 + i ) );
143                     }
144 
145                     if ( isEnableDistAttn[ i ] )
146                     {
147                         regLightEnable &= ~( 1 << ( 24 + i ) );
148                     }
149 
150                     regLightEnableEach |= ( i << ( count++ * 4 ) );
151                 }
152 
153                 // 0x08f ライトの有効無効を設定
154                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN( count );
155                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN0 );
156 
157                 // 0x1c0 グローバルアンビエントの設定
158                 *command++ = globalAmbientB | globalAmbientG << 10 | globalAmbientR << 20;
159                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_AMBIENT );
160 
161                 // 0x1c2 光源数の設定
162                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_NUM( count );
163                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_NUM );
164 
165                 // 0x1c3
166                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE0(
167                     fresnelSelector,
168                     layerConfig,
169                     isEnableShadowPrimary,
170                     isEnableShadowSecondary,
171                     isInvertShadow,
172                     isEnableShadowAlpha,
173                     bumpSelector,
174                     shadowSelector,
175                     isEnableClampHighLights,
176                     bumpMode,
177                     isEnableBumpRenorm );
178                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE0 );
179 
180                 // 0x1c4
181                 *command++ = regLightEnable;
182                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE1 );
183 
184                 // 0x1c6 ライトの有効無効を設定
185                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN_INV( count );
186                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN1 );
187 
188                 // 0x1d9
189                 *command++ = regLightEnableEach;
190                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_EN_ID );
191                 return command;
192             }
193 
194             //------------------------------------------------------------------------------
195 
MakeLightSourceCommand(u32 * command) const196             u32* FragmentLight::MakeLightSourceCommand( u32* command ) const
197             {
198                 // 各光源ごとの設定
199                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
200                 {
201                     if ( isEnable[ i ] == false ) continue;
202 
203                     command = source[ i ].MakeCommand( command );
204                 }
205 
206                 return command;
207             }
208 
209             //------------------------------------------------------------------------------
210 
MakeAllCommand(u32 * command) const211             u32* FragmentLight::MakeAllCommand( u32* command ) const
212             {
213             #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // デバッグ用
214                 u32 * start = command;
215             #endif
216 
217                 command = MakeLutConfigCommand( command );
218 
219                 command = MakeLightEnvCommand( command );
220 
221                 command = MakeLightSourceCommand( command );
222 
223 
224             #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // デバッグ用
225                 static int a = 0;
226                 if ( ++a == 10 )
227                 {
228                     for ( u32* i = start; i != command; i +=2 )
229                     {
230                         NN_LOG( "0x%08x 0x%08x\n", *i, *(i+1) );
231                     }
232                 }
233             #endif
234 
235                 return command;
236             }
237 
238             //------------------------------------------------------------------------------
239 
FragmentLight()240             FragmentLight::FragmentLight()
241                 : globalAmbientR( 0 ),
242                   globalAmbientG( 0 ),
243                   globalAmbientB( 0 ),
244                   layerConfig( PICA_DATA_FRAG_LIGHT_ENV_LAYER_CONFIG0 ),
245                   fresnelSelector( PICA_DATA_FRAG_LIGHT_ENV_NO_FRESNEL ),
246                   shadowSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ),
247                   bumpMode( PICA_DATA_FRAG_LIGHT_ENV_BUMP_NOT_USED_DMP ),
248                   bumpSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ),
249                   isEnableShadowPrimary( false ),
250                   isEnableShadowSecondary( false ),
251                   isEnableShadowAlpha( false ),
252                   isInvertShadow( false ),
253                   isEnableBumpRenorm( false ),
254                   isEnableClampHighLights( true ),
255                   isEnableLutD0( false ),
256                   isEnableLutD1( false ),
257                   isEnableLutRef1( true )
258             {
259                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
260                 {
261                     isEnable[ i ]         = false;
262                     isEnableSpot[ i ]     = false;
263                     isEnableDistAttn[ i ] = false;
264                     isShadowed[ i ]       = false;
265                     source[ i ].id        = i;
266                 }
267             }
268 
269             //------------------------------------------------------------------------------
270 
LutConfig()271             FragmentLight::LutConfig::LutConfig()
272                 : input( PICA_DATA_FRAG_LIGHT_ENV_NH_DMP ),
273                   isAbs( false ),
274                   scale( PICA_DATA_FRAG_LIGHT_ENV_LUTSCALE_1_0 )
275             {
276             }
277 
278         } // namespace CTR
279     } // namespace gr
280 } // namespace nn
281