mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
VideoCommon: Handle emboss texgen with only a single normal
Fixes a large number of effects in Rogue Squadron 2 and 3.
This commit is contained in:
parent
39b2854b98
commit
2a5c77f43f
@ -25,6 +25,7 @@
|
|||||||
#include "VideoCommon/Statistics.h"
|
#include "VideoCommon/Statistics.h"
|
||||||
#include "VideoCommon/VertexLoaderBase.h"
|
#include "VideoCommon/VertexLoaderBase.h"
|
||||||
#include "VideoCommon/VertexLoaderManager.h"
|
#include "VideoCommon/VertexLoaderManager.h"
|
||||||
|
#include "VideoCommon/VertexShaderManager.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
#include "VideoCommon/XFMemory.h"
|
#include "VideoCommon/XFMemory.h"
|
||||||
|
|
||||||
@ -90,10 +91,7 @@ void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_
|
|||||||
TransformUnit::TransformPosition(&m_vertex, outVertex);
|
TransformUnit::TransformPosition(&m_vertex, outVertex);
|
||||||
outVertex->normal = {};
|
outVertex->normal = {};
|
||||||
if (VertexLoaderManager::g_current_components & VB_HAS_NORMAL)
|
if (VertexLoaderManager::g_current_components & VB_HAS_NORMAL)
|
||||||
{
|
TransformUnit::TransformNormal(&m_vertex, outVertex);
|
||||||
TransformUnit::TransformNormal(
|
|
||||||
&m_vertex, (VertexLoaderManager::g_current_components & VB_HAS_BINORMAL) != 0, outVertex);
|
|
||||||
}
|
|
||||||
TransformUnit::TransformColor(&m_vertex, outVertex);
|
TransformUnit::TransformColor(&m_vertex, outVertex);
|
||||||
TransformUnit::TransformTexCoord(&m_vertex, outVertex);
|
TransformUnit::TransformTexCoord(&m_vertex, outVertex);
|
||||||
|
|
||||||
@ -230,6 +228,18 @@ void SWVertexLoader::ParseVertex(const PortableVertexDeclaration& vdec, int inde
|
|||||||
{
|
{
|
||||||
ReadVertexAttribute<float>(&m_vertex.normal[i][0], src, vdec.normals[i], 0, 3, false);
|
ReadVertexAttribute<float>(&m_vertex.normal[i][0], src, vdec.normals[i], 0, 3, false);
|
||||||
}
|
}
|
||||||
|
if (!vdec.normals[1].enable)
|
||||||
|
{
|
||||||
|
m_vertex.normal[1][0] = VertexShaderManager::constants.cached_tangent[0];
|
||||||
|
m_vertex.normal[1][1] = VertexShaderManager::constants.cached_tangent[1];
|
||||||
|
m_vertex.normal[1][2] = VertexShaderManager::constants.cached_tangent[2];
|
||||||
|
}
|
||||||
|
if (!vdec.normals[2].enable)
|
||||||
|
{
|
||||||
|
m_vertex.normal[2][0] = VertexShaderManager::constants.cached_binormal[0];
|
||||||
|
m_vertex.normal[2][1] = VertexShaderManager::constants.cached_binormal[1];
|
||||||
|
m_vertex.normal[2][2] = VertexShaderManager::constants.cached_binormal[2];
|
||||||
|
}
|
||||||
|
|
||||||
ParseColorAttributes(&m_vertex, src, vdec);
|
ParseColorAttributes(&m_vertex, src, vdec);
|
||||||
|
|
||||||
|
@ -90,23 +90,15 @@ void TransformPosition(const InputVertexData* src, OutputVertexData* dst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformNormal(const InputVertexData* src, bool nbt, OutputVertexData* dst)
|
void TransformNormal(const InputVertexData* src, OutputVertexData* dst)
|
||||||
{
|
{
|
||||||
const float* mat = &xfmem.normalMatrices[(src->posMtx & 31) * 3];
|
const float* mat = &xfmem.normalMatrices[(src->posMtx & 31) * 3];
|
||||||
|
|
||||||
if (nbt)
|
|
||||||
{
|
|
||||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
||||||
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
|
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
|
||||||
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
|
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
|
||||||
dst->normal[0].Normalize();
|
dst->normal[0].Normalize();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
|
||||||
dst->normal[0].Normalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TransformTexCoordRegular(const TexMtxInfo& texinfo, int coordNum,
|
static void TransformTexCoordRegular(const TexMtxInfo& texinfo, int coordNum,
|
||||||
const InputVertexData* srcVertex, OutputVertexData* dstVertex)
|
const InputVertexData* srcVertex, OutputVertexData* dstVertex)
|
||||||
|
@ -9,7 +9,7 @@ struct OutputVertexData;
|
|||||||
namespace TransformUnit
|
namespace TransformUnit
|
||||||
{
|
{
|
||||||
void TransformPosition(const InputVertexData* src, OutputVertexData* dst);
|
void TransformPosition(const InputVertexData* src, OutputVertexData* dst);
|
||||||
void TransformNormal(const InputVertexData* src, bool nbt, OutputVertexData* dst);
|
void TransformNormal(const InputVertexData* src, OutputVertexData* dst);
|
||||||
void TransformColor(const InputVertexData* src, OutputVertexData* dst);
|
void TransformColor(const InputVertexData* src, OutputVertexData* dst);
|
||||||
void TransformTexCoord(const InputVertexData* src, OutputVertexData* dst);
|
void TransformTexCoord(const InputVertexData* src, OutputVertexData* dst);
|
||||||
} // namespace TransformUnit
|
} // namespace TransformUnit
|
||||||
|
@ -90,6 +90,9 @@ struct VertexShaderConstants
|
|||||||
|
|
||||||
// .x - texMtxInfo, .y - postMtxInfo, [0..1].z = color, [0..1].w = alpha
|
// .x - texMtxInfo, .y - postMtxInfo, [0..1].z = color, [0..1].w = alpha
|
||||||
std::array<uint4, 8> xfmem_pack1;
|
std::array<uint4, 8> xfmem_pack1;
|
||||||
|
|
||||||
|
float4 cached_tangent;
|
||||||
|
float4 cached_binormal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GeometryShaderConstants
|
struct GeometryShaderConstants
|
||||||
|
@ -296,6 +296,8 @@ void WriteSwitch(ShaderCode& out, APIType ApiType, std::string_view variable,
|
|||||||
#define I_POSTTRANSFORMMATRICES "cpostmtx"
|
#define I_POSTTRANSFORMMATRICES "cpostmtx"
|
||||||
#define I_PIXELCENTERCORRECTION "cpixelcenter"
|
#define I_PIXELCENTERCORRECTION "cpixelcenter"
|
||||||
#define I_VIEWPORT_SIZE "cviewport"
|
#define I_VIEWPORT_SIZE "cviewport"
|
||||||
|
#define I_CACHED_TANGENT "ctangent"
|
||||||
|
#define I_CACHED_BINORMAL "cbinormal"
|
||||||
|
|
||||||
#define I_STEREOPARAMS "cstereo"
|
#define I_STEREOPARAMS "cstereo"
|
||||||
#define I_LINEPTPARAMS "clinept"
|
#define I_LINEPTPARAMS "clinept"
|
||||||
@ -317,6 +319,8 @@ static const char s_shader_uniforms[] = "\tuint components;\n"
|
|||||||
"\tfloat4 " I_PIXELCENTERCORRECTION ";\n"
|
"\tfloat4 " I_PIXELCENTERCORRECTION ";\n"
|
||||||
"\tfloat2 " I_VIEWPORT_SIZE ";\n"
|
"\tfloat2 " I_VIEWPORT_SIZE ";\n"
|
||||||
"\tuint4 xfmem_pack1[8];\n"
|
"\tuint4 xfmem_pack1[8];\n"
|
||||||
|
"\tfloat4 " I_CACHED_TANGENT ";\n"
|
||||||
|
"\tfloat4 " I_CACHED_BINORMAL ";\n"
|
||||||
"\t#define xfmem_texMtxInfo(i) (xfmem_pack1[(i)].x)\n"
|
"\t#define xfmem_texMtxInfo(i) (xfmem_pack1[(i)].x)\n"
|
||||||
"\t#define xfmem_postMtxInfo(i) (xfmem_pack1[(i)].y)\n"
|
"\t#define xfmem_postMtxInfo(i) (xfmem_pack1[(i)].y)\n"
|
||||||
"\t#define xfmem_color(i) (xfmem_pack1[(i)].z)\n"
|
"\t#define xfmem_color(i) (xfmem_pack1[(i)].z)\n"
|
||||||
|
@ -169,12 +169,18 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config
|
|||||||
"if ((components & {}u) != 0u) // VB_HAS_TANGENT\n",
|
"if ((components & {}u) != 0u) // VB_HAS_TANGENT\n",
|
||||||
VB_HAS_TANGENT);
|
VB_HAS_TANGENT);
|
||||||
out.Write(" _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, rawtangent));\n"
|
out.Write(" _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, rawtangent));\n"
|
||||||
|
"else\n"
|
||||||
|
" _tangent = float3(dot(N0, " I_CACHED_TANGENT ".xyz), dot(N1, " I_CACHED_TANGENT
|
||||||
|
".xyz), dot(N2, " I_CACHED_TANGENT ".xyz));\n"
|
||||||
"\n"
|
"\n"
|
||||||
"float3 _binormal = float3(0.0, 0.0, 0.0);\n"
|
"float3 _binormal = float3(0.0, 0.0, 0.0);\n"
|
||||||
"if ((components & {}u) != 0u) // VB_HAS_BINORMAL\n",
|
"if ((components & {}u) != 0u) // VB_HAS_BINORMAL\n",
|
||||||
VB_HAS_BINORMAL);
|
VB_HAS_BINORMAL);
|
||||||
out.Write(" _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, "
|
out.Write(" _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, "
|
||||||
"rawbinormal));\n"
|
"rawbinormal));\n"
|
||||||
|
"else\n"
|
||||||
|
" _binormal = float3(dot(N0, " I_CACHED_BINORMAL ".xyz), dot(N1, " I_CACHED_BINORMAL
|
||||||
|
".xyz), dot(N2, " I_CACHED_BINORMAL ".xyz));\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
|
||||||
// Hardware Lighting
|
// Hardware Lighting
|
||||||
@ -449,12 +455,9 @@ static void GenVertexShaderTexGens(APIType api_type, u32 num_texgen, ShaderCode&
|
|||||||
for (u32 i = 0; i < num_texgen; i++)
|
for (u32 i = 0; i < num_texgen; i++)
|
||||||
out.Write(" case {}u: output_tex.xyz = o.tex{}; break;\n", i, i);
|
out.Write(" case {}u: output_tex.xyz = o.tex{}; break;\n", i, i);
|
||||||
out.Write(" default: output_tex.xyz = float3(0.0, 0.0, 0.0); break;\n"
|
out.Write(" default: output_tex.xyz = float3(0.0, 0.0, 0.0); break;\n"
|
||||||
" }}\n");
|
|
||||||
out.Write(" if ((components & {}u) != 0u) {{ // VB_HAS_TANGENT | VB_HAS_BINORMAL\n",
|
|
||||||
VB_HAS_TANGENT | VB_HAS_BINORMAL);
|
|
||||||
out.Write(" float3 ldir = normalize(" I_LIGHTS "[light].pos.xyz - pos.xyz);\n"
|
|
||||||
" output_tex.xyz += float3(dot(ldir, _tangent), dot(ldir, _binormal), 0.0);\n"
|
|
||||||
" }}\n"
|
" }}\n"
|
||||||
|
" float3 ldir = normalize(" I_LIGHTS "[light].pos.xyz - pos.xyz);\n"
|
||||||
|
" output_tex.xyz += float3(dot(ldir, _tangent), dot(ldir, _binormal), 0.0);\n"
|
||||||
" }}\n"
|
" }}\n"
|
||||||
" break;\n\n");
|
" break;\n\n");
|
||||||
out.Write(" case {:s}:\n", TexGenType::Color0);
|
out.Write(" case {:s}:\n", TexGenType::Color0);
|
||||||
|
@ -215,6 +215,20 @@ int VertexLoaderARM64::ReadVertex(VertexComponentFormat attribute, ComponentForm
|
|||||||
m_float_emit.STR(128, coords, EncodeRegTo64(scratch2_reg), ArithOption(remaining_reg, true));
|
m_float_emit.STR(128, coords, EncodeRegTo64(scratch2_reg), ArithOption(remaining_reg, true));
|
||||||
SetJumpTarget(dont_store);
|
SetJumpTarget(dont_store);
|
||||||
}
|
}
|
||||||
|
else if (native_format == &m_native_vtx_decl.normals[1])
|
||||||
|
{
|
||||||
|
FixupBranch dont_store = CBNZ(remaining_reg);
|
||||||
|
MOVP2R(EncodeRegTo64(scratch2_reg), VertexLoaderManager::tangent_cache.data());
|
||||||
|
m_float_emit.STR(128, IndexType::Unsigned, coords, EncodeRegTo64(scratch2_reg), 0);
|
||||||
|
SetJumpTarget(dont_store);
|
||||||
|
}
|
||||||
|
else if (native_format == &m_native_vtx_decl.normals[2])
|
||||||
|
{
|
||||||
|
FixupBranch dont_store = CBNZ(remaining_reg);
|
||||||
|
MOVP2R(EncodeRegTo64(scratch2_reg), VertexLoaderManager::binormal_cache.data());
|
||||||
|
m_float_emit.STR(128, IndexType::Unsigned, coords, EncodeRegTo64(scratch2_reg), 0);
|
||||||
|
SetJumpTarget(dont_store);
|
||||||
|
}
|
||||||
|
|
||||||
native_format->components = count_out;
|
native_format->components = count_out;
|
||||||
native_format->enable = true;
|
native_format->enable = true;
|
||||||
|
@ -35,6 +35,8 @@ namespace VertexLoaderManager
|
|||||||
std::array<u32, 3> position_matrix_index_cache;
|
std::array<u32, 3> position_matrix_index_cache;
|
||||||
// 3 vertices, 4 floats each to allow SIMD overwrite
|
// 3 vertices, 4 floats each to allow SIMD overwrite
|
||||||
alignas(sizeof(std::array<float, 4>)) std::array<std::array<float, 4>, 3> position_cache;
|
alignas(sizeof(std::array<float, 4>)) std::array<std::array<float, 4>, 3> position_cache;
|
||||||
|
alignas(sizeof(std::array<float, 4>)) std::array<float, 4> tangent_cache;
|
||||||
|
alignas(sizeof(std::array<float, 4>)) std::array<float, 4> binormal_cache;
|
||||||
|
|
||||||
static NativeVertexFormatMap s_native_vertex_map;
|
static NativeVertexFormatMap s_native_vertex_map;
|
||||||
static NativeVertexFormat* s_current_vtx_fmt;
|
static NativeVertexFormat* s_current_vtx_fmt;
|
||||||
|
@ -55,6 +55,10 @@ void UpdateVertexArrayPointers();
|
|||||||
// These arrays are in reverse order.
|
// These arrays are in reverse order.
|
||||||
extern std::array<std::array<float, 4>, 3> position_cache;
|
extern std::array<std::array<float, 4>, 3> position_cache;
|
||||||
extern std::array<u32, 3> position_matrix_index_cache;
|
extern std::array<u32, 3> position_matrix_index_cache;
|
||||||
|
// Store the tangent and binormal vectors for games that use emboss texgens when the vertex format
|
||||||
|
// doesn't include them (e.g. RS2 and RS3). These too are 4 floats each for SIMD overwrites.
|
||||||
|
extern std::array<float, 4> tangent_cache;
|
||||||
|
extern std::array<float, 4> binormal_cache;
|
||||||
|
|
||||||
// VB_HAS_X. Bitmask telling what vertex components are present.
|
// VB_HAS_X. Bitmask telling what vertex components are present.
|
||||||
extern u32 g_current_components;
|
extern u32 g_current_components;
|
||||||
|
@ -127,6 +127,22 @@ int VertexLoaderX64::ReadVertex(OpArg data, VertexComponentFormat attribute, Com
|
|||||||
MOVUPS(MPIC(VertexLoaderManager::position_cache.data(), scratch3, SCALE_4), coords);
|
MOVUPS(MPIC(VertexLoaderManager::position_cache.data(), scratch3, SCALE_4), coords);
|
||||||
SetJumpTarget(dont_store);
|
SetJumpTarget(dont_store);
|
||||||
}
|
}
|
||||||
|
else if (native_format == &m_native_vtx_decl.normals[1])
|
||||||
|
{
|
||||||
|
TEST(32, R(remaining_reg), R(remaining_reg));
|
||||||
|
FixupBranch dont_store = J_CC(CC_NZ);
|
||||||
|
// For similar reasons, the cached tangent and binormal are 4 floats each
|
||||||
|
MOVUPS(MPIC(VertexLoaderManager::tangent_cache.data()), coords);
|
||||||
|
SetJumpTarget(dont_store);
|
||||||
|
}
|
||||||
|
else if (native_format == &m_native_vtx_decl.normals[2])
|
||||||
|
{
|
||||||
|
CMP(32, R(remaining_reg), R(remaining_reg));
|
||||||
|
FixupBranch dont_store = J_CC(CC_NZ);
|
||||||
|
// For similar reasons, the cached tangent and binormal are 4 floats each
|
||||||
|
MOVUPS(MPIC(VertexLoaderManager::binormal_cache.data()), coords);
|
||||||
|
SetJumpTarget(dont_store);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int elem_size = GetElementSize(format);
|
int elem_size = GetElementSize(format);
|
||||||
@ -217,7 +233,9 @@ int VertexLoaderX64::ReadVertex(OpArg data, VertexComponentFormat attribute, Com
|
|||||||
dest.AddMemOffset(sizeof(float));
|
dest.AddMemOffset(sizeof(float));
|
||||||
|
|
||||||
// zfreeze
|
// zfreeze
|
||||||
if (native_format == &m_native_vtx_decl.position)
|
if (native_format == &m_native_vtx_decl.position ||
|
||||||
|
native_format == &m_native_vtx_decl.normals[1] ||
|
||||||
|
native_format == &m_native_vtx_decl.normals[2])
|
||||||
{
|
{
|
||||||
if (cpu_info.bSSE4_1)
|
if (cpu_info.bSSE4_1)
|
||||||
{
|
{
|
||||||
|
@ -40,14 +40,22 @@ constexpr float FracAdjust(float val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, u32 N>
|
template <typename T, u32 N>
|
||||||
void ReadIndirect(const T* data)
|
void ReadIndirect(VertexLoader* loader, const T* data)
|
||||||
{
|
{
|
||||||
static_assert(3 == N || 9 == N, "N is only sane as 3 or 9!");
|
static_assert(3 == N || 9 == N, "N is only sane as 3 or 9!");
|
||||||
DataReader dst(g_vertex_manager_write_ptr, nullptr);
|
DataReader dst(g_vertex_manager_write_ptr, nullptr);
|
||||||
|
|
||||||
for (u32 i = 0; i < N; ++i)
|
for (u32 i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
dst.Write(FracAdjust(Common::FromBigEndian(data[i])));
|
const float value = FracAdjust(Common::FromBigEndian(data[i]));
|
||||||
|
if (loader->m_remaining == 0)
|
||||||
|
{
|
||||||
|
if (i >= 3 && i < 6)
|
||||||
|
VertexLoaderManager::tangent_cache[i - 3] = value;
|
||||||
|
else if (i >= 6 && i < 9)
|
||||||
|
VertexLoaderManager::binormal_cache[i - 6] = value;
|
||||||
|
}
|
||||||
|
dst.Write(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_vertex_manager_write_ptr = dst.GetPointer();
|
g_vertex_manager_write_ptr = dst.GetPointer();
|
||||||
@ -57,10 +65,10 @@ void ReadIndirect(const T* data)
|
|||||||
template <typename T, u32 N>
|
template <typename T, u32 N>
|
||||||
struct Normal_Direct
|
struct Normal_Direct
|
||||||
{
|
{
|
||||||
static void function([[maybe_unused]] VertexLoader* loader)
|
static void function(VertexLoader* loader)
|
||||||
{
|
{
|
||||||
const auto source = reinterpret_cast<const T*>(DataGetPosition());
|
const auto source = reinterpret_cast<const T*>(DataGetPosition());
|
||||||
ReadIndirect<T, N * 3>(source);
|
ReadIndirect<T, N * 3>(loader, source);
|
||||||
DataSkip<N * 3 * sizeof(T)>();
|
DataSkip<N * 3 * sizeof(T)>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +76,7 @@ struct Normal_Direct
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename I, typename T, u32 N, u32 Offset>
|
template <typename I, typename T, u32 N, u32 Offset>
|
||||||
void Normal_Index_Offset()
|
void Normal_Index_Offset(VertexLoader* loader)
|
||||||
{
|
{
|
||||||
static_assert(std::is_unsigned_v<I>, "Only unsigned I is sane!");
|
static_assert(std::is_unsigned_v<I>, "Only unsigned I is sane!");
|
||||||
|
|
||||||
@ -76,24 +84,24 @@ void Normal_Index_Offset()
|
|||||||
const auto data = reinterpret_cast<const T*>(
|
const auto data = reinterpret_cast<const T*>(
|
||||||
VertexLoaderManager::cached_arraybases[CPArray::Normal] +
|
VertexLoaderManager::cached_arraybases[CPArray::Normal] +
|
||||||
(index * g_main_cp_state.array_strides[CPArray::Normal]) + sizeof(T) * 3 * Offset);
|
(index * g_main_cp_state.array_strides[CPArray::Normal]) + sizeof(T) * 3 * Offset);
|
||||||
ReadIndirect<T, N * 3>(data);
|
ReadIndirect<T, N * 3>(loader, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename I, typename T, u32 N>
|
template <typename I, typename T, u32 N>
|
||||||
struct Normal_Index
|
struct Normal_Index
|
||||||
{
|
{
|
||||||
static void function([[maybe_unused]] VertexLoader* loader) { Normal_Index_Offset<I, T, N, 0>(); }
|
static void function(VertexLoader* loader) { Normal_Index_Offset<I, T, N, 0>(loader); }
|
||||||
static constexpr u32 size = sizeof(I);
|
static constexpr u32 size = sizeof(I);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename I, typename T>
|
template <typename I, typename T>
|
||||||
struct Normal_Index_Indices3
|
struct Normal_Index_Indices3
|
||||||
{
|
{
|
||||||
static void function([[maybe_unused]] VertexLoader* loader)
|
static void function(VertexLoader* loader)
|
||||||
{
|
{
|
||||||
Normal_Index_Offset<I, T, 1, 0>();
|
Normal_Index_Offset<I, T, 1, 0>(loader);
|
||||||
Normal_Index_Offset<I, T, 1, 1>();
|
Normal_Index_Offset<I, T, 1, 1>(loader);
|
||||||
Normal_Index_Offset<I, T, 1, 2>();
|
Normal_Index_Offset<I, T, 1, 2>(loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr u32 size = sizeof(I) * 3;
|
static constexpr u32 size = sizeof(I) * 3;
|
||||||
|
@ -453,6 +453,7 @@ void VertexManagerBase::Flush()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CalculateBinormals(VertexLoaderManager::GetCurrentVertexFormat());
|
||||||
// Calculate ZSlope for zfreeze
|
// Calculate ZSlope for zfreeze
|
||||||
VertexShaderManager::SetConstants();
|
VertexShaderManager::SetConstants();
|
||||||
if (!bpmem.genMode.zfreeze)
|
if (!bpmem.genMode.zfreeze)
|
||||||
@ -595,6 +596,31 @@ void VertexManagerBase::CalculateZSlope(NativeVertexFormat* format)
|
|||||||
m_zslope.dirty = true;
|
m_zslope.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VertexManagerBase::CalculateBinormals(NativeVertexFormat* format)
|
||||||
|
{
|
||||||
|
const PortableVertexDeclaration vert_decl = format->GetVertexDeclaration();
|
||||||
|
|
||||||
|
// Only update the binormal/tangent vertex shader constants if the vertex format lacks binormals
|
||||||
|
// (VertexLoaderManager::binormal_cache gets updated by the vertex loader when binormals are
|
||||||
|
// present, though)
|
||||||
|
if (vert_decl.normals[1].enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VertexLoaderManager::tangent_cache[3] = 0;
|
||||||
|
VertexLoaderManager::binormal_cache[3] = 0;
|
||||||
|
|
||||||
|
if (VertexShaderManager::constants.cached_tangent != VertexLoaderManager::tangent_cache)
|
||||||
|
{
|
||||||
|
VertexShaderManager::constants.cached_tangent = VertexLoaderManager::tangent_cache;
|
||||||
|
VertexShaderManager::dirty = true;
|
||||||
|
}
|
||||||
|
if (VertexShaderManager::constants.cached_binormal != VertexLoaderManager::binormal_cache)
|
||||||
|
{
|
||||||
|
VertexShaderManager::constants.cached_binormal = VertexLoaderManager::binormal_cache;
|
||||||
|
VertexShaderManager::dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VertexManagerBase::UpdatePipelineConfig()
|
void VertexManagerBase::UpdatePipelineConfig()
|
||||||
{
|
{
|
||||||
NativeVertexFormat* vertex_format = VertexLoaderManager::GetCurrentVertexFormat();
|
NativeVertexFormat* vertex_format = VertexLoaderManager::GetCurrentVertexFormat();
|
||||||
|
@ -172,6 +172,7 @@ protected:
|
|||||||
u32 GetRemainingIndices(OpcodeDecoder::Primitive primitive) const;
|
u32 GetRemainingIndices(OpcodeDecoder::Primitive primitive) const;
|
||||||
|
|
||||||
void CalculateZSlope(NativeVertexFormat* format);
|
void CalculateZSlope(NativeVertexFormat* format);
|
||||||
|
void CalculateBinormals(NativeVertexFormat* format);
|
||||||
void LoadTextures();
|
void LoadTextures();
|
||||||
|
|
||||||
u8* m_cur_buffer_pointer = nullptr;
|
u8* m_cur_buffer_pointer = nullptr;
|
||||||
|
@ -253,23 +253,24 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
|
|||||||
"float4 pos = float4(dot(P0, rawpos), dot(P1, rawpos), dot(P2, rawpos), 1.0);\n");
|
"float4 pos = float4(dot(P0, rawpos), dot(P1, rawpos), dot(P2, rawpos), 1.0);\n");
|
||||||
if ((uid_data->components & VB_HAS_NORMAL) != 0)
|
if ((uid_data->components & VB_HAS_NORMAL) != 0)
|
||||||
{
|
{
|
||||||
|
if ((uid_data->components & VB_HAS_TANGENT) == 0)
|
||||||
|
out.Write("float3 rawtangent = " I_CACHED_TANGENT ".xyz;\n");
|
||||||
|
if ((uid_data->components & VB_HAS_BINORMAL) == 0)
|
||||||
|
out.Write("float3 rawbinormal = " I_CACHED_BINORMAL ".xyz;\n");
|
||||||
|
|
||||||
// Only the first normal gets normalized (TODO: why?)
|
// Only the first normal gets normalized (TODO: why?)
|
||||||
out.Write("float3 _normal = normalize(float3(dot(N0, rawnormal), dot(N1, rawnormal), dot(N2, "
|
out.Write("float3 _normal = normalize(float3(dot(N0, rawnormal), dot(N1, rawnormal), dot(N2, "
|
||||||
"rawnormal)));\n");
|
"rawnormal)));\n"
|
||||||
|
"float3 _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, "
|
||||||
|
"rawtangent));\n"
|
||||||
|
"float3 _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, "
|
||||||
|
"rawbinormal));\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out.Write("float3 _normal = float3(0.0, 0.0, 0.0);\n");
|
out.Write("float3 _normal = float3(0.0, 0.0, 0.0);\n");
|
||||||
}
|
out.Write("float3 _binormal = float3(0.0, 0.0, 0.0);\n");
|
||||||
if ((uid_data->components & VB_HAS_TANGENT) != 0)
|
out.Write("float3 _tangent = float3(0.0, 0.0, 0.0);\n");
|
||||||
{
|
|
||||||
out.Write("float3 _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, "
|
|
||||||
"rawtangent));\n");
|
|
||||||
}
|
|
||||||
if ((uid_data->components & VB_HAS_BINORMAL) != 0)
|
|
||||||
{
|
|
||||||
out.Write("float3 _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, "
|
|
||||||
"rawbinormal));\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write("o.pos = float4(dot(" I_PROJECTION "[0], pos), dot(" I_PROJECTION
|
out.Write("o.pos = float4(dot(" I_PROJECTION "[0], pos), dot(" I_PROJECTION
|
||||||
@ -341,22 +342,12 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
|
|||||||
{
|
{
|
||||||
case TexGenType::EmbossMap: // calculate tex coords into bump map
|
case TexGenType::EmbossMap: // calculate tex coords into bump map
|
||||||
|
|
||||||
if ((uid_data->components & (VB_HAS_TANGENT | VB_HAS_BINORMAL)) != 0)
|
|
||||||
{
|
|
||||||
// transform the light dir into tangent space
|
// transform the light dir into tangent space
|
||||||
out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n",
|
out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n",
|
||||||
LIGHT_POS_PARAMS(texinfo.embosslightshift));
|
LIGHT_POS_PARAMS(texinfo.embosslightshift));
|
||||||
out.Write(
|
out.Write(
|
||||||
"o.tex{}.xyz = o.tex{}.xyz + float3(dot(ldir, _tangent), dot(ldir, _binormal), 0.0);\n",
|
"o.tex{}.xyz = o.tex{}.xyz + float3(dot(ldir, _tangent), dot(ldir, _binormal), 0.0);\n",
|
||||||
i, texinfo.embosssourceshift);
|
i, texinfo.embosssourceshift);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The following assert was triggered in House of the Dead Overkill and Star Wars Rogue
|
|
||||||
// Squadron 2
|
|
||||||
// ASSERT(0); // should have normals
|
|
||||||
out.Write("o.tex{}.xyz = o.tex{}.xyz;\n", i, texinfo.embosssourceshift);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TexGenType::Color0:
|
case TexGenType::Color0:
|
||||||
|
Loading…
Reference in New Issue
Block a user