diff options
Diffstat (limited to 'src/video_core/swrasterizer/rasterizer.cpp')
| -rw-r--r-- | src/video_core/swrasterizer/rasterizer.cpp | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 20addf0bd..8b7b1defb 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -5,6 +5,7 @@ #include <algorithm> #include <array> #include <cmath> +#include <tuple> #include "common/assert.h" #include "common/bit_field.h" #include "common/color.h" @@ -23,6 +24,7 @@ #include "video_core/regs_texturing.h" #include "video_core/shader/shader.h" #include "video_core/swrasterizer/framebuffer.h" +#include "video_core/swrasterizer/proctex.h" #include "video_core/swrasterizer/rasterizer.h" #include "video_core/swrasterizer/texturing.h" #include "video_core/texture/texture_decode.h" @@ -69,6 +71,49 @@ static int SignedArea(const Math::Vec2<Fix12P4>& vtx1, const Math::Vec2<Fix12P4> return Math::Cross(vec1, vec2).z; }; +/// Convert a 3D vector for cube map coordinates to 2D texture coordinates along with the face name +static std::tuple<float24, float24, PAddr> ConvertCubeCoord(float24 u, float24 v, float24 w, + const TexturingRegs& regs) { + const float abs_u = std::abs(u.ToFloat32()); + const float abs_v = std::abs(v.ToFloat32()); + const float abs_w = std::abs(w.ToFloat32()); + float24 x, y, z; + PAddr addr; + if (abs_u > abs_v && abs_u > abs_w) { + if (u > float24::FromFloat32(0)) { + addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveX); + y = -v; + } else { + addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeX); + y = v; + } + x = -w; + z = u; + } else if (abs_v > abs_w) { + if (v > float24::FromFloat32(0)) { + addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveY); + x = u; + } else { + addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeY); + x = -u; + } + y = w; + z = v; + } else { + if (w > float24::FromFloat32(0)) { + addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveZ); + y = -v; + } else { + addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeZ); + y = v; + } + x = u; + z = w; + } + const float24 half = float24::FromFloat32(0.5f); + return std::make_tuple(x / z * half + half, y / z * half + half, addr); +} + MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); /** @@ -268,7 +313,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve uv[2].u() = GetInterpolatedAttribute(v0.tc2.u(), v1.tc2.u(), v2.tc2.u()); uv[2].v() = GetInterpolatedAttribute(v0.tc2.v(), v1.tc2.v(), v2.tc2.v()); - Math::Vec4<u8> texture_color[3]{}; + Math::Vec4<u8> texture_color[4]{}; for (int i = 0; i < 3; ++i) { const auto& texture = textures[i]; if (!texture.enabled) @@ -283,10 +328,16 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve // Only unit 0 respects the texturing type (according to 3DBrew) // TODO: Refactor so cubemaps and shadowmaps can be handled + PAddr texture_address = texture.config.GetPhysicalAddress(); if (i == 0) { switch (texture.config.type) { case TexturingRegs::TextureConfig::Texture2D: break; + case TexturingRegs::TextureConfig::TextureCube: { + auto w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); + std::tie(u, v, texture_address) = ConvertCubeCoord(u, v, w, regs.texturing); + break; + } case TexturingRegs::TextureConfig::Projection2D: { auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); u /= tc0_w; @@ -321,8 +372,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve t = texture.config.height - 1 - GetWrappedTexCoord(texture.config.wrap_t, t, texture.config.height); - u8* texture_data = - Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); + const u8* texture_data = Memory::GetPhysicalPointer(texture_address); auto info = Texture::TextureInfo::FromPicaRegister(texture.config, texture.format); @@ -334,6 +384,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve } } + // sample procedural texture + if (regs.texturing.main_config.texture3_enable) { + const auto& proctex_uv = uv[regs.texturing.main_config.texture3_coordinates]; + texture_color[3] = ProcTex(proctex_uv.u().ToFloat32(), proctex_uv.v().ToFloat32(), + g_state.regs.texturing, g_state.proctex); + } + // Texture environment - consists of 6 stages of color and alpha combining. // // Color combiners take three input color values from some source (e.g. interpolated @@ -376,6 +433,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve case Source::Texture2: return texture_color[2]; + case Source::Texture3: + return texture_color[3]; + case Source::PreviousBuffer: return combiner_buffer; |
