mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	pica: Implement decoding of basic fragment lighting components.
- Diffuse - Distance attenuation - float16/float20 types - Vertex Shader 'view' output
This commit is contained in:
		
							parent
							
								
									281bc90ad2
								
							
						
					
					
						commit
						b003075570
					
				
					 5 changed files with 120 additions and 15 deletions
				
			
		|  | @ -68,6 +68,8 @@ static void InitScreenCoordinates(OutputVertex& vtx) | ||||||
| 
 | 
 | ||||||
|     float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; |     float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; | ||||||
|     vtx.color *= inv_w; |     vtx.color *= inv_w; | ||||||
|  |     vtx.view *= inv_w; | ||||||
|  |     vtx.quat *= inv_w; | ||||||
|     vtx.tc0 *= inv_w; |     vtx.tc0 *= inv_w; | ||||||
|     vtx.tc1 *= inv_w; |     vtx.tc1 *= inv_w; | ||||||
|     vtx.tc2 *= inv_w; |     vtx.tc2 *= inv_w; | ||||||
|  |  | ||||||
|  | @ -241,7 +241,8 @@ struct Regs { | ||||||
|     TextureConfig texture0; |     TextureConfig texture0; | ||||||
|     INSERT_PADDING_WORDS(0x8); |     INSERT_PADDING_WORDS(0x8); | ||||||
|     BitField<0, 4, TextureFormat> texture0_format; |     BitField<0, 4, TextureFormat> texture0_format; | ||||||
|     INSERT_PADDING_WORDS(0x2); |     BitField<0, 1, u32> fragment_lighting_enable; | ||||||
|  |     INSERT_PADDING_WORDS(0x1); | ||||||
|     TextureConfig texture1; |     TextureConfig texture1; | ||||||
|     BitField<0, 4, TextureFormat> texture1_format; |     BitField<0, 4, TextureFormat> texture1_format; | ||||||
|     INSERT_PADDING_WORDS(0x2); |     INSERT_PADDING_WORDS(0x2); | ||||||
|  | @ -645,6 +646,22 @@ struct Regs { | ||||||
| 
 | 
 | ||||||
|     INSERT_PADDING_WORDS(0x20); |     INSERT_PADDING_WORDS(0x20); | ||||||
| 
 | 
 | ||||||
|  |     enum class LightingSampler { | ||||||
|  |         Distribution0 = 0, | ||||||
|  |         Distribution1 = 1, | ||||||
|  |         Fresnel = 3, | ||||||
|  |         Blue = 4, | ||||||
|  |         Green = 5, | ||||||
|  |         Red = 6, | ||||||
|  |         SpotlightAttenuation = 8, | ||||||
|  |         DistanceAttenuation = 16, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     enum class LightingLutInput { | ||||||
|  |         NH = 0, // Cosine of the angle between the normal and half-angle vectors
 | ||||||
|  |         LN = 3, // Cosine of the angle between the light and the normal vectors
 | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     struct { |     struct { | ||||||
|         union LightColor { |         union LightColor { | ||||||
|             BitField< 0, 10, u32> b; |             BitField< 0, 10, u32> b; | ||||||
|  | @ -664,17 +681,21 @@ struct Regs { | ||||||
| 
 | 
 | ||||||
|             struct { |             struct { | ||||||
|                 // Encoded as 16-bit floating point
 |                 // Encoded as 16-bit floating point
 | ||||||
|                 u16 x; |                 union { | ||||||
|                 u16 y; |                     BitField< 0, 16, u32> x; | ||||||
|                 u16 z; |                     BitField<16, 16, u32> y; | ||||||
|                 u16 unk; |                 }; | ||||||
|  |                 union { | ||||||
|  |                     BitField< 0, 16, u32> z; | ||||||
|  |                 }; | ||||||
| 
 | 
 | ||||||
|                 INSERT_PADDING_WORDS(0x3); |                 INSERT_PADDING_WORDS(0x3); | ||||||
| 
 | 
 | ||||||
|                 // 1.f if 0, otherwise 0.f
 |                 union { | ||||||
|                 BitField<0, 1, u32> w; |                     BitField<0, 1, u32> w; // 1.f if 0, otherwise 0.f
 | ||||||
|             } position; |                     BitField<1, 1, u32> two_sided_diffuse; // when disabled, clamp dot-product to 0
 | ||||||
| 
 |                 }; | ||||||
|  |             }; | ||||||
| 
 | 
 | ||||||
|             BitField<0, 20, u32> dist_atten_bias; |             BitField<0, 20, u32> dist_atten_bias; | ||||||
|             BitField<0, 20, u32> dist_atten_scale; |             BitField<0, 20, u32> dist_atten_scale; | ||||||
|  | @ -722,7 +743,27 @@ struct Regs { | ||||||
|         // registers is written to, the behavior will be the same.
 |         // registers is written to, the behavior will be the same.
 | ||||||
|         u32 lut_data[8]; |         u32 lut_data[8]; | ||||||
| 
 | 
 | ||||||
|         INSERT_PADDING_WORDS(0x9); |         union { | ||||||
|  |             BitField< 1, 1, u32> d0; | ||||||
|  |             BitField< 5, 1, u32> d1; | ||||||
|  |             BitField< 9, 1, u32> sp; | ||||||
|  |             BitField<13, 1, u32> fr; | ||||||
|  |             BitField<17, 1, u32> rb; | ||||||
|  |             BitField<21, 1, u32> rg; | ||||||
|  |             BitField<25, 1, u32> rr; | ||||||
|  |         } abs_lut_input; | ||||||
|  | 
 | ||||||
|  |         union { | ||||||
|  |             BitField< 0, 3, u32> d0; | ||||||
|  |             BitField< 4, 3, u32> d1; | ||||||
|  |             BitField< 8, 3, u32> sp; | ||||||
|  |             BitField<12, 3, u32> fr; | ||||||
|  |             BitField<16, 3, u32> rb; | ||||||
|  |             BitField<20, 3, u32> rg; | ||||||
|  |             BitField<24, 3, u32> rr; | ||||||
|  |         } lut_input; | ||||||
|  | 
 | ||||||
|  |         INSERT_PADDING_WORDS(0x7); | ||||||
| 
 | 
 | ||||||
|         union { |         union { | ||||||
|             // There are 8 light enable "slots", corresponding to the total number of lights
 |             // There are 8 light enable "slots", corresponding to the total number of lights
 | ||||||
|  | @ -1095,6 +1136,7 @@ ASSERT_REG_POSITION(viewport_corner, 0x68); | ||||||
| ASSERT_REG_POSITION(texture0_enable, 0x80); | ASSERT_REG_POSITION(texture0_enable, 0x80); | ||||||
| ASSERT_REG_POSITION(texture0, 0x81); | ASSERT_REG_POSITION(texture0, 0x81); | ||||||
| ASSERT_REG_POSITION(texture0_format, 0x8e); | ASSERT_REG_POSITION(texture0_format, 0x8e); | ||||||
|  | ASSERT_REG_POSITION(fragment_lighting_enable, 0x8f); | ||||||
| ASSERT_REG_POSITION(texture1, 0x91); | ASSERT_REG_POSITION(texture1, 0x91); | ||||||
| ASSERT_REG_POSITION(texture1_format, 0x96); | ASSERT_REG_POSITION(texture1_format, 0x96); | ||||||
| ASSERT_REG_POSITION(texture2, 0x99); | ASSERT_REG_POSITION(texture2, 0x99); | ||||||
|  | @ -1109,6 +1151,7 @@ ASSERT_REG_POSITION(tev_stage5, 0xf8); | ||||||
| ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd); | ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd); | ||||||
| ASSERT_REG_POSITION(output_merger, 0x100); | ASSERT_REG_POSITION(output_merger, 0x100); | ||||||
| ASSERT_REG_POSITION(framebuffer, 0x110); | ASSERT_REG_POSITION(framebuffer, 0x110); | ||||||
|  | ASSERT_REG_POSITION(lighting, 0x140); | ||||||
| ASSERT_REG_POSITION(vertex_attributes, 0x200); | ASSERT_REG_POSITION(vertex_attributes, 0x200); | ||||||
| ASSERT_REG_POSITION(index_array, 0x227); | ASSERT_REG_POSITION(index_array, 0x227); | ||||||
| ASSERT_REG_POSITION(num_vertices, 0x228); | ASSERT_REG_POSITION(num_vertices, 0x228); | ||||||
|  |  | ||||||
|  | @ -121,4 +121,60 @@ private: | ||||||
| 
 | 
 | ||||||
| static_assert(sizeof(float24) == sizeof(float), "Shader JIT assumes float24 is implemented as a 32-bit float"); | static_assert(sizeof(float24) == sizeof(float), "Shader JIT assumes float24 is implemented as a 32-bit float"); | ||||||
| 
 | 
 | ||||||
|  | struct float16 { | ||||||
|  |     // 10 bit mantissa, 5 bit exponent, 1 bit sign
 | ||||||
|  |     // TODO: No idea if this works as intended
 | ||||||
|  |     static float16 FromRawFloat16(u32 hex) { | ||||||
|  |         float16 ret; | ||||||
|  |         if ((hex & 0xFFFF) == 0) { | ||||||
|  |             ret.value = 0; | ||||||
|  |         } else { | ||||||
|  |             u32 mantissa = hex & 0x3FF; | ||||||
|  |             u32 exponent = (hex >> 10) & 0x1F; | ||||||
|  |             u32 sign = (hex >> 15) & 1; | ||||||
|  |             ret.value = std::pow(2.0f, (float)exponent - 15.0f) * (1.0f + mantissa * std::pow(2.0f, -10.f)); | ||||||
|  |             if (sign) | ||||||
|  |                 ret.value = -ret.value; | ||||||
|  |         } | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     float ToFloat32() const { | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     // Stored as a regular float, merely for convenience
 | ||||||
|  |     // TODO: Perform proper arithmetic on this!
 | ||||||
|  |     float value; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct float20 { | ||||||
|  |     // 12 bit mantissa, 7 bit exponent, 1 bit sign
 | ||||||
|  |     // TODO: No idea if this works as intended
 | ||||||
|  |     static float20 FromRawFloat20(u32 hex) { | ||||||
|  |         float20 ret; | ||||||
|  |         if ((hex & 0xFFFFF) == 0) { | ||||||
|  |             ret.value = 0; | ||||||
|  |         } else { | ||||||
|  |             u32 mantissa = hex & 0xFFF; | ||||||
|  |             u32 exponent = (hex >> 12) & 0x7F; | ||||||
|  |             u32 sign = (hex >> 19) & 1; | ||||||
|  |             ret.value = std::pow(2.0f, (float)exponent - 63.0f) * (1.0f + mantissa * std::pow(2.0f, -12.f)); | ||||||
|  |             if (sign) | ||||||
|  |                 ret.value = -ret.value; | ||||||
|  |         } | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     float ToFloat32() const { | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     // Stored as a regular float, merely for convenience
 | ||||||
|  |     // TODO: Perform proper arithmetic on this!
 | ||||||
|  |     float value; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| } // namespace Pica
 | } // namespace Pica
 | ||||||
|  |  | ||||||
|  | @ -134,11 +134,13 @@ OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attr | ||||||
|             std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f)); |             std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     LOG_TRACE(Render_Software, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), quat (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)", |     LOG_TRACE(Render_Software, "Output vertex: pos(%.2f, %.2f, %.2f, %.2f), quat(%.2f, %.2f, %.2f, %.2f), " | ||||||
|  |         "col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f), view(%.2f, %.2f, %.2f)", | ||||||
|         ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(), |         ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(), | ||||||
|         ret.quat.x.ToFloat32(), ret.quat.y.ToFloat32(), ret.quat.z.ToFloat32(), ret.quat.w.ToFloat32(), |         ret.quat.x.ToFloat32(), ret.quat.y.ToFloat32(), ret.quat.z.ToFloat32(), ret.quat.w.ToFloat32(), | ||||||
|         ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(), |         ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(), | ||||||
|         ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32()); |         ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32(), | ||||||
|  |         ret.view.x.ToFloat32(), ret.view.y.ToFloat32(), ret.view.z.ToFloat32()); | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -37,17 +37,19 @@ struct OutputVertex { | ||||||
|     Math::Vec4<float24> color; |     Math::Vec4<float24> color; | ||||||
|     Math::Vec2<float24> tc0; |     Math::Vec2<float24> tc0; | ||||||
|     Math::Vec2<float24> tc1; |     Math::Vec2<float24> tc1; | ||||||
|     float24 pad[6]; |     INSERT_PADDING_WORDS(2); | ||||||
|  |     Math::Vec3<float24> view; | ||||||
|  |     INSERT_PADDING_WORDS(1); | ||||||
|     Math::Vec2<float24> tc2; |     Math::Vec2<float24> tc2; | ||||||
| 
 | 
 | ||||||
|     // Padding for optimal alignment
 |     // Padding for optimal alignment
 | ||||||
|     float24 pad2[4]; |     INSERT_PADDING_WORDS(4); | ||||||
| 
 | 
 | ||||||
|     // Attributes used to store intermediate results
 |     // Attributes used to store intermediate results
 | ||||||
| 
 | 
 | ||||||
|     // position after perspective divide
 |     // position after perspective divide
 | ||||||
|     Math::Vec3<float24> screenpos; |     Math::Vec3<float24> screenpos; | ||||||
|     float24 pad3; |     INSERT_PADDING_WORDS(1); | ||||||
| 
 | 
 | ||||||
|     // Linear interpolation
 |     // Linear interpolation
 | ||||||
|     // factor: 0=this, 1=vtx
 |     // factor: 0=this, 1=vtx
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue