1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: gr_FragmentLight.cpp 4 5 Copyright (C)2009-2012 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: 46347 $ 14 *---------------------------------------------------------------------------*/ 15 16 #include <nn/gr/CTR/gr_FragmentLight.h> 17 18 namespace nn 19 { 20 namespace gr 21 { 22 namespace CTR 23 { 24 MakeAllCommand(bit32 * command) const25 bit32* FragmentLight::Source::MakeAllCommand( 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 MakeCommand(bit32 * command) const50 bit32* FragmentLight::Source::MakeCommand( bit32* command ) const 51 { 52 return MakeAllCommand( command ); 53 } 54 55 //------------------------------------------------------------------------------ 56 MakeColorCommand(bit32 * command) const57 bit32* FragmentLight::Source::MakeColorCommand( bit32* command ) const 58 { 59 bit32 reg = PICA_REG_FRAG_LIGHT_START + id * PICA_FRAG_LIGHT_STRIDE; 60 61 *command++ = specular0B | specular0G << 10 | specular0R << 20; // specular0 62 *command++ = PICA_CMD_HEADER_BURSTSEQ( reg, 4 ); // Header 63 64 *command++ = specular1B | specular1G << 10 | specular1R << 20; // specular1 65 *command++ = diffuseB | diffuseG << 10 | diffuseR << 20; // Diffuse 66 67 *command++ = ambientB | ambientG << 10 | ambientR << 20; // Ambient 68 *command++ = 0; 69 70 return command; 71 } 72 73 //------------------------------------------------------------------------------ 74 MakeGeometryCommand(bit32 * command) const75 bit32* FragmentLight::Source::MakeGeometryCommand( bit32* command ) const 76 { 77 bit32 reg = PICA_REG_FRAG_LIGHT_START + id * PICA_FRAG_LIGHT_STRIDE + 0x4; 78 79 *command++ = posXY; 80 *command++ = PICA_CMD_HEADER_BURSTSEQ( reg, 8 ); 81 82 *command++ = posZ; 83 *command++ = spotDirectionXY; 84 85 *command++ = spotDirectionZ; 86 *command++ = 0; 87 88 *command++ = isInfinity | 89 ( isEnableTwoSideDiffuse ? 1 : 0 ) << 1 | 90 ( isEnableGeomFactor0 ? 1 : 0 ) << 2 | 91 ( isEnableGeomFactor1 ? 1 : 0 ) << 3; 92 *command++ = distAttnBias; 93 94 *command++ = distAttnScale; 95 *command++ = 0; 96 97 return command; 98 } 99 100 //------------------------------------------------------------------------------ 101 Source()102 FragmentLight::Source::Source() 103 : id( 0 ), 104 isEnableTwoSideDiffuse( false ), 105 isEnableGeomFactor0( false ), 106 isEnableGeomFactor1( false ), 107 diffuseR( 255 ), 108 diffuseG( 255 ), 109 diffuseB( 255 ), 110 ambientR( 0 ), 111 ambientG( 0 ), 112 ambientB( 0 ), 113 specular0R( 255 ), 114 specular0G( 255 ), 115 specular0B( 255 ), 116 specular1R( 255 ), 117 specular1G( 255 ), 118 specular1B( 255 ), 119 posXY( 0 ), 120 posZ( 0 ), 121 isInfinity( 0 ), 122 distAttnBias( 0 ), 123 distAttnScale( 0 ), 124 spotDirectionXY( 0 ), 125 spotDirectionZ( 0 ) 126 { 127 } 128 129 //------------------------------------------------------------------------------ 130 MakeLutConfigCommand(bit32 * command) const131 bit32* FragmentLight::MakeLutConfigCommand( bit32* command ) const 132 { 133 // 0x1d0 134 *command++ = PICA_CMD_DATA_FRAG_LIGHT_ABSLUTINPUT( 135 lutConfigD0.isAbs, 136 lutConfigD1.isAbs, 137 lutConfigSP.isAbs, 138 lutConfigFR.isAbs, 139 lutConfigRB.isAbs, 140 lutConfigRG.isAbs, 141 lutConfigRR.isAbs ); 142 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_ABSLUTINPUT ); 143 144 // 0x1d1 145 *command++ = PICA_CMD_DATA_FRAG_LIGHT_LUTINPUT( 146 lutConfigD0.input, 147 lutConfigD1.input, 148 lutConfigSP.input, 149 lutConfigFR.input, 150 lutConfigRB.input, 151 lutConfigRG.input, 152 lutConfigRR.input ); 153 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_LUTINPUT ); 154 155 // 0x1d2 156 *command++ = PICA_CMD_DATA_FRAG_LIGHT_LUTSCALE( 157 lutConfigD0.scale, 158 lutConfigD1.scale, 159 lutConfigSP.scale, 160 lutConfigFR.scale, 161 lutConfigRB.scale, 162 lutConfigRG.scale, 163 lutConfigRR.scale ); 164 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_LUTSCALE ); 165 166 return command; 167 } 168 169 //------------------------------------------------------------------------------ 170 MakeLightEnvCommand(bit32 * command,bool isAddDummyCommand) const171 bit32* FragmentLight::MakeLightEnvCommand( bit32* command, bool isAddDummyCommand ) const 172 { 173 bit32 regLightEnable = 0xff00ffff; 174 bit32 regLightEnableEach = 0; 175 s32 count = 0; 176 177 regLightEnable |= PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE1_LUT( 178 isEnableLutD0, 179 isEnableLutD1, 180 fresnelSelector, 181 isEnableLutRefl ); 182 183 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i ) 184 { 185 if ( isEnable[ i ] == false ) 186 { 187 continue; 188 } 189 190 if ( isShadowed[ i ] ) 191 { 192 regLightEnable &= ~( 1 << i ); 193 } 194 195 if ( isEnableSpot[ i ] ) 196 { 197 regLightEnable &= ~( 1 << ( 8 + i ) ); 198 } 199 200 if ( isEnableDistAttn[ i ] ) 201 { 202 regLightEnable &= ~( 1 << ( 24 + i ) ); 203 } 204 205 regLightEnableEach |= ( i << ( count++ * 4 ) ); 206 } 207 208 // Before converting 0x08f, send dummy command 209 if ( isAddDummyCommand ) 210 { 211 *command++ = 0x0; 212 *command++ = PICA_CMD_HEADER_BURST_BE( PICA_REG_TEXTURE_FUNC, 0x3, 0x0 ); 213 *command++ = 0x0; 214 *command++ = 0x0; 215 } 216 217 // Set whether the 0x08f light is enabled or disabled 218 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN( count ); 219 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN0 ); 220 221 // 0x1c0 global ambient settings 222 *command++ = globalAmbientB | globalAmbientG << 10 | globalAmbientR << 20; 223 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_AMBIENT ); 224 225 // 0x1c2 number of light source setting 226 *command++ = PICA_CMD_DATA_FRAG_LIGHT_NUM( count ); 227 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_NUM ); 228 229 // 0x1c3 230 *command++ = PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE0( 231 fresnelSelector, 232 layerConfig, 233 isEnableShadowPrimary, 234 isEnableShadowSecondary, 235 isInvertShadow, 236 isEnableShadowAlpha, 237 bumpSelector, 238 shadowSelector, 239 isEnableClampHighLights, 240 bumpMode, 241 isEnableBumpRenorm ); 242 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE0 ); 243 244 // 0x1c4 245 *command++ = regLightEnable; 246 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE1 ); 247 248 // Set whether the 0x1c6 light is enabled or disabled 249 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN_INV( count ); 250 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN1 ); 251 252 // 0x1d9 253 *command++ = regLightEnableEach; 254 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_EN_ID ); 255 return command; 256 } 257 258 //------------------------------------------------------------------------------ 259 MakeLightSourceCommand(bit32 * command) const260 bit32* FragmentLight::MakeLightSourceCommand( bit32* command ) const 261 { 262 // Sets for each light source 263 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i ) 264 { 265 if ( isEnable[ i ] == false ) continue; 266 267 command = source[ i ].MakeCommand( command ); 268 } 269 270 return command; 271 } 272 273 //------------------------------------------------------------------------------ 274 MakeAllCommand(bit32 * command,bool isAddDummyCommand) const275 bit32* FragmentLight::MakeAllCommand( bit32* command, bool isAddDummyCommand ) const 276 { 277 #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // For debugging 278 bit32 * start = command; 279 #endif 280 281 command = MakeLutConfigCommand( command ); 282 283 command = MakeLightEnvCommand( command, isAddDummyCommand ); 284 285 command = MakeLightSourceCommand( command ); 286 287 288 #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // For debugging 289 static int a = 0; 290 if ( ++a == 10 ) 291 { 292 for ( u32* i = start; i != command; i +=2 ) 293 { 294 NN_LOG( "0x%08x 0x%08x\n", *i, *(i+1) ); 295 } 296 } 297 #endif 298 299 return command; 300 } 301 302 //------------------------------------------------------------------------------ 303 MakeDisableCommand(bit32 * command,bool isAddDummyCommand)304 bit32* FragmentLight::MakeDisableCommand( bit32* command, bool isAddDummyCommand ) 305 { 306 const u32 lightNum = 0; 307 308 // Before converting 0x08f, send dummy command 309 if ( isAddDummyCommand ) 310 { 311 *command++ = 0x0; 312 *command++ = PICA_CMD_HEADER_BURST_BE( PICA_REG_TEXTURE_FUNC, 0x3, 0x0 ); 313 314 *command++ = 0x0; 315 *command++ = 0x0; 316 } 317 318 // Sets 0x08f light to disabled 319 *command++ = 0; 320 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN0 ); 321 322 // Sets 0x1c6 light to disabled 323 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN_INV( lightNum ); 324 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN1 ); 325 326 // Sets the number of 0x1c2 light sources to 0 327 *command++ = lightNum; 328 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_NUM ); 329 330 return command; 331 } 332 333 //------------------------------------------------------------------------------ 334 FragmentLight()335 FragmentLight::FragmentLight() 336 : globalAmbientR( 0 ), 337 globalAmbientG( 0 ), 338 globalAmbientB( 0 ), 339 layerConfig( PICA_DATA_FRAG_LIGHT_ENV_LAYER_CONFIG0 ), 340 fresnelSelector( PICA_DATA_FRAG_LIGHT_ENV_NO_FRESNEL ), 341 shadowSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ), 342 bumpMode( PICA_DATA_FRAG_LIGHT_ENV_BUMP_NOT_USED_DMP ), 343 bumpSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ), 344 isEnableShadowPrimary( false ), 345 isEnableShadowSecondary( false ), 346 isEnableShadowAlpha( false ), 347 isInvertShadow( false ), 348 isEnableBumpRenorm( false ), 349 isEnableClampHighLights( true ), 350 isEnableLutD0( false ), 351 isEnableLutD1( false ), 352 isEnableLutRefl( true ) 353 { 354 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i ) 355 { 356 isEnable[ i ] = false; 357 isEnableSpot[ i ] = false; 358 isEnableDistAttn[ i ] = false; 359 isShadowed[ i ] = false; 360 source[ i ].id = i; 361 } 362 } 363 364 //------------------------------------------------------------------------------ 365 LutConfig()366 FragmentLight::LutConfig::LutConfig() 367 : input( PICA_DATA_FRAG_LIGHT_ENV_NH_DMP ), 368 isAbs( false ), 369 scale( PICA_DATA_FRAG_LIGHT_ENV_LUTSCALE_1_0 ) 370 { 371 } 372 373 } // namespace CTR 374 } // namespace gr 375 } // namespace nn 376