diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 57d5e8253..e6cccebf6 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -182,19 +182,22 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 182 | RasterizerOpenGL::~RasterizerOpenGL() {} | 182 | RasterizerOpenGL::~RasterizerOpenGL() {} |
| 183 | 183 | ||
| 184 | /** | 184 | /** |
| 185 | * This is a helper function to resolve an issue with opposite quaternions being interpolated by | 185 | * This is a helper function to resolve an issue when interpolating opposite quaternions. See below |
| 186 | * OpenGL. See below for a detailed description of this issue (yuriks): | 186 | * for a detailed description of this issue (yuriks): |
| 187 | * | 187 | * |
| 188 | * For any rotation, there are two quaternions Q, and -Q, that represent the same rotation. If you | 188 | * For any rotation, there are two quaternions Q, and -Q, that represent the same rotation. If you |
| 189 | * interpolate two quaternions that are opposite, instead of going from one rotation to another | 189 | * interpolate two quaternions that are opposite, instead of going from one rotation to another |
| 190 | * using the shortest path, you'll go around the longest path. You can test if two quaternions are | 190 | * using the shortest path, you'll go around the longest path. You can test if two quaternions are |
| 191 | * opposite by checking if Dot(Q1, W2) < 0. In that case, you can flip either of them, therefore | 191 | * opposite by checking if Dot(Q1, Q2) < 0. In that case, you can flip either of them, therefore |
| 192 | * making Dot(-Q1, W2) positive. | 192 | * making Dot(Q1, -Q2) positive. |
| 193 | * | 193 | * |
| 194 | * NOTE: This solution corrects this issue per-vertex before passing the quaternions to OpenGL. This | 194 | * This solution corrects this issue per-vertex before passing the quaternions to OpenGL. This is |
| 195 | * should be correct for nearly all cases, however a more correct implementation (but less trivial | 195 | * correct for most cases but can still rotate around the long way sometimes. An implementation |
| 196 | * and perhaps unnecessary) would be to handle this per-fragment, by interpolating the quaternions | 196 | * which did `lerp(lerp(Q1, Q2), Q3)` (with proper weighting), applying the dot product check |
| 197 | * manually using two Lerps, and doing this correction before each Lerp. | 197 | * between each step would work for those cases at the cost of being more complex to implement. |
| 198 | * | ||
| 199 | * Fortunately however, the 3DS hardware happens to also use this exact same logic to work around | ||
| 200 | * these issues, making this basic implementation actually more accurate to the hardware. | ||
| 198 | */ | 201 | */ |
| 199 | static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) { | 202 | static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) { |
| 200 | Math::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()}; | 203 | Math::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()}; |