mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Pica/Rasterizer: Make orient2d a free function and rename it to SignedArea.
This commit is contained in:
		
							parent
							
								
									47543d62cf
								
							
						
					
					
						commit
						9675d19b47
					
				
					 1 changed files with 39 additions and 32 deletions
				
			
		|  | @ -55,30 +55,45 @@ static void SetDepth(int x, int y, u16 value) { | ||||||
|     *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value; |     *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
 | ||||||
|  | struct Fix12P4 { | ||||||
|  |     Fix12P4() {} | ||||||
|  |     Fix12P4(u16 val) : val(val) {} | ||||||
|  | 
 | ||||||
|  |     static u16 FracMask() { return 0xF; } | ||||||
|  |     static u16 IntMask() { return (u16)~0xF; } | ||||||
|  | 
 | ||||||
|  |     operator u16() const { | ||||||
|  |         return val; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool operator < (const Fix12P4& oth) const { | ||||||
|  |         return (u16)*this < (u16)oth; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     u16 val; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Calculate signed area of the triangle spanned by the three argument vertices. | ||||||
|  |  * The sign denotes an orientation. | ||||||
|  |  * | ||||||
|  |  * @todo define orientation concretely. | ||||||
|  |  */ | ||||||
|  | static int SignedArea (const Math::Vec2<Fix12P4>& vtx1, | ||||||
|  |                        const Math::Vec2<Fix12P4>& vtx2, | ||||||
|  |                        const Math::Vec2<Fix12P4>& vtx3) { | ||||||
|  |     const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0); | ||||||
|  |     const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0); | ||||||
|  |     // TODO: There is a very small chance this will overflow for sizeof(int) == 4
 | ||||||
|  |     return Math::Cross(vec1, vec2).z; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| void ProcessTriangle(const VertexShader::OutputVertex& v0, | void ProcessTriangle(const VertexShader::OutputVertex& v0, | ||||||
|                      const VertexShader::OutputVertex& v1, |                      const VertexShader::OutputVertex& v1, | ||||||
|                      const VertexShader::OutputVertex& v2) |                      const VertexShader::OutputVertex& v2) | ||||||
| { | { | ||||||
|     // NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
 |  | ||||||
|     struct Fix12P4 { |  | ||||||
|         Fix12P4() {} |  | ||||||
|         Fix12P4(u16 val) : val(val) {} |  | ||||||
| 
 |  | ||||||
|         static u16 FracMask() { return 0xF; } |  | ||||||
|         static u16 IntMask() { return (u16)~0xF; } |  | ||||||
| 
 |  | ||||||
|         operator u16() const { |  | ||||||
|             return val; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool operator < (const Fix12P4& oth) const { |  | ||||||
|             return (u16)*this < (u16)oth; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|     private: |  | ||||||
|         u16 val; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     // vertex positions in rasterizer coordinates
 |     // vertex positions in rasterizer coordinates
 | ||||||
|     auto FloatToFix = [](float24 flt) { |     auto FloatToFix = [](float24 flt) { | ||||||
|                           return Fix12P4(static_cast<unsigned short>(flt.ToFloat32() * 16.0f)); |                           return Fix12P4(static_cast<unsigned short>(flt.ToFloat32() * 16.0f)); | ||||||
|  | @ -86,14 +101,6 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | ||||||
|     auto ScreenToRasterizerCoordinates = [FloatToFix](const Math::Vec3<float24> vec) { |     auto ScreenToRasterizerCoordinates = [FloatToFix](const Math::Vec3<float24> vec) { | ||||||
|                                              return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)}; |                                              return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)}; | ||||||
|                                          }; |                                          }; | ||||||
|     static auto orient2d = [](const Math::Vec2<Fix12P4>& vtx1, |  | ||||||
|                               const Math::Vec2<Fix12P4>& vtx2, |  | ||||||
|                               const Math::Vec2<Fix12P4>& vtx3) { |  | ||||||
|         const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0); |  | ||||||
|         const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0); |  | ||||||
|         // TODO: There is a very small chance this will overflow for sizeof(int) == 4
 |  | ||||||
|         return Math::Cross(vec1, vec2).z; |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     Math::Vec3<Fix12P4> vtxpos[3]{ ScreenToRasterizerCoordinates(v0.screenpos), |     Math::Vec3<Fix12P4> vtxpos[3]{ ScreenToRasterizerCoordinates(v0.screenpos), | ||||||
|                                    ScreenToRasterizerCoordinates(v1.screenpos), |                                    ScreenToRasterizerCoordinates(v1.screenpos), | ||||||
|  | @ -107,7 +114,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | ||||||
|     if (registers.cull_mode != Regs::CullMode::KeepAll) { |     if (registers.cull_mode != Regs::CullMode::KeepAll) { | ||||||
|         // Cull away triangles which are wound clockwise.
 |         // Cull away triangles which are wound clockwise.
 | ||||||
|         // TODO: A check for degenerate triangles ("== 0") should be considered for CullMode::KeepAll
 |         // TODO: A check for degenerate triangles ("== 0") should be considered for CullMode::KeepAll
 | ||||||
|         if (orient2d(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) |         if (SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -153,9 +160,9 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | ||||||
|         for (u16 x = min_x; x < max_x; x += 0x10) { |         for (u16 x = min_x; x < max_x; x += 0x10) { | ||||||
| 
 | 
 | ||||||
|             // Calculate the barycentric coordinates w0, w1 and w2
 |             // Calculate the barycentric coordinates w0, w1 and w2
 | ||||||
|             int w0 = bias0 + orient2d(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); |             int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); | ||||||
|             int w1 = bias1 + orient2d(vtxpos[2].xy(), vtxpos[0].xy(), {x, y}); |             int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y}); | ||||||
|             int w2 = bias2 + orient2d(vtxpos[0].xy(), vtxpos[1].xy(), {x, y}); |             int w2 = bias2 + SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), {x, y}); | ||||||
|             int wsum = w0 + w1 + w2; |             int wsum = w0 + w1 + w2; | ||||||
| 
 | 
 | ||||||
|             // If current pixel is not covered by the current primitive
 |             // If current pixel is not covered by the current primitive
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue