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: 29908 $
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(bit32 * command) const25             bit32* FragmentLight::Source::MakeCommand( bit32* command ) const
26             {
27                 bit32 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(bit32 * command) const79             bit32* FragmentLight::MakeLutConfigCommand( bit32* 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(bit32 * command,bool isAddDummyCommand) const119             bit32* FragmentLight::MakeLightEnvCommand( bit32* command, bool isAddDummyCommand ) const
120             {
121                 bit32 regLightEnable     = 0xff00ffff;
122                 bit32 regLightEnableEach = 0;
123                 s32 count = 0;
124 
125                 regLightEnable |= PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE1_LUT(
126                     isEnableLutD0,
127                     isEnableLutD1,
128                     fresnelSelector,
129                     isEnableLutRefl );
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                 if ( isAddDummyCommand )
155                 {
156                     *command++ = 0x0;
157                     *command++ = PICA_CMD_HEADER_BURST_BE( PICA_REG_TEXTURE_FUNC, 0x3, 0x0 );
158                     *command++ = 0x0;
159                     *command++ = 0x0;
160                 }
161 
162                 // 0x08f ライトの有効無効を設定
163                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN( count );
164                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN0 );
165 
166                 // 0x1c0 グローバルアンビエントの設定
167                 *command++ = globalAmbientB | globalAmbientG << 10 | globalAmbientR << 20;
168                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_AMBIENT );
169 
170                 // 0x1c2 光源数の設定
171                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_NUM( count );
172                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_NUM );
173 
174                 // 0x1c3
175                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE0(
176                     fresnelSelector,
177                     layerConfig,
178                     isEnableShadowPrimary,
179                     isEnableShadowSecondary,
180                     isInvertShadow,
181                     isEnableShadowAlpha,
182                     bumpSelector,
183                     shadowSelector,
184                     isEnableClampHighLights,
185                     bumpMode,
186                     isEnableBumpRenorm );
187                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE0 );
188 
189                 // 0x1c4
190                 *command++ = regLightEnable;
191                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE1 );
192 
193                 // 0x1c6 ライトの有効無効を設定
194                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN_INV( count );
195                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN1 );
196 
197                 // 0x1d9
198                 *command++ = regLightEnableEach;
199                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_EN_ID );
200                 return command;
201             }
202 
203             //------------------------------------------------------------------------------
204 
MakeLightSourceCommand(bit32 * command) const205             bit32* FragmentLight::MakeLightSourceCommand( bit32* command ) const
206             {
207                 // 各光源ごとの設定
208                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
209                 {
210                     if ( isEnable[ i ] == false ) continue;
211 
212                     command = source[ i ].MakeCommand( command );
213                 }
214 
215                 return command;
216             }
217 
218             //------------------------------------------------------------------------------
219 
MakeAllCommand(bit32 * command,bool isAddDummyCommand) const220             bit32* FragmentLight::MakeAllCommand( bit32* command, bool isAddDummyCommand ) const
221             {
222             #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // デバッグ用
223                 bit32 * start = command;
224             #endif
225 
226                 command = MakeLutConfigCommand( command );
227 
228                 command = MakeLightEnvCommand( command, isAddDummyCommand );
229 
230                 command = MakeLightSourceCommand( command );
231 
232 
233             #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // デバッグ用
234                 static int a = 0;
235                 if ( ++a == 10 )
236                 {
237                     for ( u32* i = start; i != command; i +=2 )
238                     {
239                         NN_LOG( "0x%08x 0x%08x\n", *i, *(i+1) );
240                     }
241                 }
242             #endif
243 
244                 return command;
245             }
246 
247             //------------------------------------------------------------------------------
248 
FragmentLight()249             FragmentLight::FragmentLight()
250                 : globalAmbientR( 0 ),
251                   globalAmbientG( 0 ),
252                   globalAmbientB( 0 ),
253                   layerConfig( PICA_DATA_FRAG_LIGHT_ENV_LAYER_CONFIG0 ),
254                   fresnelSelector( PICA_DATA_FRAG_LIGHT_ENV_NO_FRESNEL ),
255                   shadowSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ),
256                   bumpMode( PICA_DATA_FRAG_LIGHT_ENV_BUMP_NOT_USED_DMP ),
257                   bumpSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ),
258                   isEnableShadowPrimary( false ),
259                   isEnableShadowSecondary( false ),
260                   isEnableShadowAlpha( false ),
261                   isInvertShadow( false ),
262                   isEnableBumpRenorm( false ),
263                   isEnableClampHighLights( true ),
264                   isEnableLutD0( false ),
265                   isEnableLutD1( false ),
266                   isEnableLutRefl( true )
267             {
268                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
269                 {
270                     isEnable[ i ]         = false;
271                     isEnableSpot[ i ]     = false;
272                     isEnableDistAttn[ i ] = false;
273                     isShadowed[ i ]       = false;
274                     source[ i ].id        = i;
275                 }
276             }
277 
278             //------------------------------------------------------------------------------
279 
LutConfig()280             FragmentLight::LutConfig::LutConfig()
281                 : input( PICA_DATA_FRAG_LIGHT_ENV_NH_DMP ),
282                   isAbs( false ),
283                   scale( PICA_DATA_FRAG_LIGHT_ENV_LUTSCALE_1_0 )
284             {
285             }
286 
287         } // namespace CTR
288     } // namespace gr
289 } // namespace nn
290