mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 23:59:27 +01:00
937bb2aa2e
Fixes LIT (https://bugs.dolphin-emu.org/issues/13635). The text does not include normals, but has lighting enabled. With the previous default of (0, 0, 0), lighting was always black (as dot(X, (0, 0, 0)) is always 0). It seems like the normal from the map in the background (0, 0, 1) is re-used. LIT also has the vertex color enabled while vertex color is not specified, the same as SMS's debug cubes; the default MissingColorValue GameINI value of solid white seems to work correctly in this case.
230 lines
12 KiB
C++
230 lines
12 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "VideoCommon/VertexLoader_Normal.h"
|
|
|
|
#include <array>
|
|
#include <type_traits>
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/EnumMap.h"
|
|
|
|
#include "VideoCommon/VertexLoader.h"
|
|
#include "VideoCommon/VertexLoaderManager.h"
|
|
#include "VideoCommon/VertexLoaderUtils.h"
|
|
|
|
// warning: mapping buffer should be disabled to use this
|
|
#define LOG_NORM() // PRIM_LOG("norm: {} {} {}, ", ((float*)g_vertex_manager_write_ptr)[-3],
|
|
// ((float*)g_vertex_manager_write_ptr)[-2],
|
|
// ((float*)g_vertex_manager_write_ptr)[-1]);
|
|
|
|
namespace
|
|
{
|
|
template <typename T>
|
|
constexpr float FracAdjust(T val)
|
|
{
|
|
// auto const S8FRAC = 1.f / (1u << 6);
|
|
// auto const U8FRAC = 1.f / (1u << 7);
|
|
// auto const S16FRAC = 1.f / (1u << 14);
|
|
// auto const U16FRAC = 1.f / (1u << 15);
|
|
|
|
// TODO: is this right?
|
|
return val / float(1u << (sizeof(T) * 8 - std::is_signed_v<T> - 1));
|
|
}
|
|
|
|
template <>
|
|
constexpr float FracAdjust(float val)
|
|
{
|
|
return val;
|
|
}
|
|
|
|
template <typename T, u32 N, u32 Offset>
|
|
void ReadIndirect(VertexLoader* loader, const T* data)
|
|
{
|
|
static_assert(3 == N || 9 == N, "N is only sane as 3 or 9!");
|
|
static_assert(!(Offset != 0 && 9 == N), "N == 9 only makes sense if offset == 0");
|
|
|
|
for (u32 i = Offset; i < N + Offset; ++i)
|
|
{
|
|
const float value = FracAdjust(Common::FromBigEndian(data[i]));
|
|
if (loader->m_remaining == 0)
|
|
{
|
|
if (i < 3)
|
|
VertexLoaderManager::normal_cache[i] = value;
|
|
else if (i >= 3 && i < 6)
|
|
VertexLoaderManager::tangent_cache[i - 3] = value;
|
|
else if (i >= 6 && i < 9)
|
|
VertexLoaderManager::binormal_cache[i - 6] = value;
|
|
}
|
|
DataWrite(value);
|
|
}
|
|
|
|
LOG_NORM();
|
|
}
|
|
|
|
template <typename T, u32 N>
|
|
void Normal_ReadDirect(VertexLoader* loader)
|
|
{
|
|
const auto source = reinterpret_cast<const T*>(DataGetPosition());
|
|
ReadIndirect<T, N * 3, 0>(loader, source);
|
|
DataSkip<N * 3 * sizeof(T)>();
|
|
}
|
|
|
|
template <typename I, typename T, u32 N, u32 Offset>
|
|
void Normal_ReadIndex_Offset(VertexLoader* loader)
|
|
{
|
|
static_assert(std::is_unsigned_v<I>, "Only unsigned I is sane!");
|
|
|
|
const auto index = DataRead<I>();
|
|
const auto data =
|
|
reinterpret_cast<const T*>(VertexLoaderManager::cached_arraybases[CPArray::Normal] +
|
|
(index * g_main_cp_state.array_strides[CPArray::Normal]));
|
|
ReadIndirect<T, N * 3, Offset * 3>(loader, data);
|
|
}
|
|
|
|
template <typename I, typename T, u32 N>
|
|
void Normal_ReadIndex(VertexLoader* loader)
|
|
{
|
|
Normal_ReadIndex_Offset<I, T, N, 0>(loader);
|
|
}
|
|
|
|
template <typename I, typename T>
|
|
void Normal_ReadIndex_Indices3(VertexLoader* loader)
|
|
{
|
|
Normal_ReadIndex_Offset<I, T, 1, 0>(loader);
|
|
Normal_ReadIndex_Offset<I, T, 1, 1>(loader);
|
|
Normal_ReadIndex_Offset<I, T, 1, 2>(loader);
|
|
}
|
|
|
|
using Common::EnumMap;
|
|
using Formats = EnumMap<TPipelineFunction, ComponentFormat::InvalidFloat7>;
|
|
using Elements = EnumMap<Formats, NormalComponentCount::NTB>;
|
|
using Indices = std::array<Elements, 2>;
|
|
using Types = EnumMap<Indices, VertexComponentFormat::Index16>;
|
|
|
|
consteval Types InitializeTable()
|
|
{
|
|
Types table{};
|
|
|
|
using VCF = VertexComponentFormat;
|
|
using NCC = NormalComponentCount;
|
|
using FMT = ComponentFormat;
|
|
|
|
table[VCF::Direct][false][NCC::N][FMT::UByte] = Normal_ReadDirect<u8, 1>;
|
|
table[VCF::Direct][false][NCC::N][FMT::Byte] = Normal_ReadDirect<s8, 1>;
|
|
table[VCF::Direct][false][NCC::N][FMT::UShort] = Normal_ReadDirect<u16, 1>;
|
|
table[VCF::Direct][false][NCC::N][FMT::Short] = Normal_ReadDirect<s16, 1>;
|
|
table[VCF::Direct][false][NCC::N][FMT::Float] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][false][NCC::N][FMT::InvalidFloat5] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][false][NCC::N][FMT::InvalidFloat6] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][false][NCC::N][FMT::InvalidFloat7] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::UByte] = Normal_ReadDirect<u8, 3>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::Byte] = Normal_ReadDirect<s8, 3>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::UShort] = Normal_ReadDirect<u16, 3>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::Short] = Normal_ReadDirect<s16, 3>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::Float] = Normal_ReadDirect<float, 3>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadDirect<float, 3>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadDirect<float, 3>;
|
|
table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadDirect<float, 3>;
|
|
|
|
// Same as above, since there are no indices
|
|
table[VCF::Direct][true][NCC::N][FMT::UByte] = Normal_ReadDirect<u8, 1>;
|
|
table[VCF::Direct][true][NCC::N][FMT::Byte] = Normal_ReadDirect<s8, 1>;
|
|
table[VCF::Direct][true][NCC::N][FMT::UShort] = Normal_ReadDirect<u16, 1>;
|
|
table[VCF::Direct][true][NCC::N][FMT::Short] = Normal_ReadDirect<s16, 1>;
|
|
table[VCF::Direct][true][NCC::N][FMT::Float] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][true][NCC::N][FMT::InvalidFloat5] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][true][NCC::N][FMT::InvalidFloat6] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][true][NCC::N][FMT::InvalidFloat7] = Normal_ReadDirect<float, 1>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::UByte] = Normal_ReadDirect<u8, 3>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::Byte] = Normal_ReadDirect<s8, 3>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::UShort] = Normal_ReadDirect<u16, 3>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::Short] = Normal_ReadDirect<s16, 3>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::Float] = Normal_ReadDirect<float, 3>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadDirect<float, 3>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadDirect<float, 3>;
|
|
table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadDirect<float, 3>;
|
|
|
|
table[VCF::Index8][false][NCC::N][FMT::UByte] = Normal_ReadIndex<u8, u8, 1>;
|
|
table[VCF::Index8][false][NCC::N][FMT::Byte] = Normal_ReadIndex<u8, s8, 1>;
|
|
table[VCF::Index8][false][NCC::N][FMT::UShort] = Normal_ReadIndex<u8, u16, 1>;
|
|
table[VCF::Index8][false][NCC::N][FMT::Short] = Normal_ReadIndex<u8, s16, 1>;
|
|
table[VCF::Index8][false][NCC::N][FMT::Float] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][false][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][false][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][false][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::UByte] = Normal_ReadIndex<u8, u8, 3>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::Byte] = Normal_ReadIndex<u8, s8, 3>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::UShort] = Normal_ReadIndex<u8, u16, 3>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::Short] = Normal_ReadIndex<u8, s16, 3>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::Float] = Normal_ReadIndex<u8, float, 3>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex<u8, float, 3>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex<u8, float, 3>;
|
|
table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex<u8, float, 3>;
|
|
|
|
// Same for NormalComponentCount::N; differs for NTB
|
|
table[VCF::Index8][true][NCC::N][FMT::UByte] = Normal_ReadIndex<u8, u8, 1>;
|
|
table[VCF::Index8][true][NCC::N][FMT::Byte] = Normal_ReadIndex<u8, s8, 1>;
|
|
table[VCF::Index8][true][NCC::N][FMT::UShort] = Normal_ReadIndex<u8, u16, 1>;
|
|
table[VCF::Index8][true][NCC::N][FMT::Short] = Normal_ReadIndex<u8, s16, 1>;
|
|
table[VCF::Index8][true][NCC::N][FMT::Float] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][true][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][true][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][true][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex<u8, float, 1>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::UByte] = Normal_ReadIndex_Indices3<u8, u8>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::Byte] = Normal_ReadIndex_Indices3<u8, s8>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::UShort] = Normal_ReadIndex_Indices3<u8, u16>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::Short] = Normal_ReadIndex_Indices3<u8, s16>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::Float] = Normal_ReadIndex_Indices3<u8, float>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex_Indices3<u8, float>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex_Indices3<u8, float>;
|
|
table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex_Indices3<u8, float>;
|
|
|
|
table[VCF::Index16][false][NCC::N][FMT::UByte] = Normal_ReadIndex<u16, u8, 1>;
|
|
table[VCF::Index16][false][NCC::N][FMT::Byte] = Normal_ReadIndex<u16, s8, 1>;
|
|
table[VCF::Index16][false][NCC::N][FMT::UShort] = Normal_ReadIndex<u16, u16, 1>;
|
|
table[VCF::Index16][false][NCC::N][FMT::Short] = Normal_ReadIndex<u16, s16, 1>;
|
|
table[VCF::Index16][false][NCC::N][FMT::Float] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][false][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][false][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][false][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::UByte] = Normal_ReadIndex<u16, u8, 3>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::Byte] = Normal_ReadIndex<u16, s8, 3>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::UShort] = Normal_ReadIndex<u16, u16, 3>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::Short] = Normal_ReadIndex<u16, s16, 3>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::Float] = Normal_ReadIndex<u16, float, 3>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex<u16, float, 3>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex<u16, float, 3>;
|
|
table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex<u16, float, 3>;
|
|
|
|
// Same for NormalComponentCount::N; differs for NTB
|
|
table[VCF::Index16][true][NCC::N][FMT::UByte] = Normal_ReadIndex<u16, u8, 1>;
|
|
table[VCF::Index16][true][NCC::N][FMT::Byte] = Normal_ReadIndex<u16, s8, 1>;
|
|
table[VCF::Index16][true][NCC::N][FMT::UShort] = Normal_ReadIndex<u16, u16, 1>;
|
|
table[VCF::Index16][true][NCC::N][FMT::Short] = Normal_ReadIndex<u16, s16, 1>;
|
|
table[VCF::Index16][true][NCC::N][FMT::Float] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][true][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][true][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][true][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex<u16, float, 1>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::UByte] = Normal_ReadIndex_Indices3<u16, u8>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::Byte] = Normal_ReadIndex_Indices3<u16, s8>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::UShort] = Normal_ReadIndex_Indices3<u16, u16>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::Short] = Normal_ReadIndex_Indices3<u16, s16>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::Float] = Normal_ReadIndex_Indices3<u16, float>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex_Indices3<u16, float>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex_Indices3<u16, float>;
|
|
table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex_Indices3<u16, float>;
|
|
|
|
return table;
|
|
}
|
|
|
|
constexpr Types s_table_read_normal = InitializeTable();
|
|
} // Anonymous namespace
|
|
|
|
TPipelineFunction VertexLoader_Normal::GetFunction(VertexComponentFormat type,
|
|
ComponentFormat format,
|
|
NormalComponentCount elements, bool index3)
|
|
{
|
|
return s_table_read_normal[type][index3][elements][format];
|
|
}
|