diff --git a/src/video_core/pica.h b/src/video_core/pica.h index fe20cd77d..84e3309c3 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -262,6 +262,8 @@ struct Regs { Lerp = 4, Subtract = 5, + Dot3RGB = 6, + Dot3RGBA = 7, MultiplyThenAdd = 8, AddThenMultiply = 9, }; diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index dd46f0ec3..be204ba2e 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -502,6 +502,20 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, return result.Cast(); } + // This computes the dot product of the RGB components according to GLES spec. + // Dot3RGB just stores the dot product in the RGB components. + // Dot3RGBA also stores it in the alpha component. + case Operation::Dot3RGB: + case Operation::Dot3RGBA: + { + std::array a = {input[0].r(), input[0].g(), input[0].b()}; + std::array b = {input[1].r(), input[1].g(), input[1].b()}; + + auto res = std::inner_product(a, a.end(), b, 0); + + return {res, res, res}; + } + case Operation::MultiplyThenAdd: { auto result = (input[0] * input[1] + 255 * input[2].Cast()) / 255; @@ -545,6 +559,16 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, case Operation::Subtract: return std::max(0, (int)input[0] - (int)input[1]); + case Operation::Dot3RGBA: + { + std::array a = {input[0].r(), input[0].g(), input[0].b()}; + std::array b = {input[1].r(), input[1].g(), input[1].b()}; + + auto res = std::inner_product(a, a.end(), b, 0); + + return res; + } + case Operation::MultiplyThenAdd: return std::min(255, (input[0] * input[1] + 255 * input[2]) / 255);