2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-13 02:05:51 +00:00

Convert CSpaceWarpFilter; fix up CXRayBlurFilter

This commit is contained in:
Luke Street 2020-10-03 23:36:30 -04:00
parent 3799759ca7
commit 63f7f225cc
6 changed files with 120 additions and 91 deletions

View File

@ -70,4 +70,6 @@ runtime_add_hsh(Graphics
Shaders/CRadarPaintShader.cpp Shaders/CRadarPaintShader.cpp
Shaders/CRandomStaticFilter.cpp Shaders/CRandomStaticFilter.cpp
Shaders/CScanLinesFilter.cpp Shaders/CScanLinesFilter.cpp
Shaders/CSpaceWarpFilter.cpp
Shaders/CXRayBlurFilter.cpp
) )

View File

@ -25,6 +25,13 @@ public:
TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */ TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */
}; };
struct RGBA8 {
u8 r;
u8 g;
u8 b;
u8 a;
};
private: private:
ETexelFormat x0_fmt; ETexelFormat x0_fmt;
u16 x4_w; u16 x4_w;

View File

@ -12,13 +12,6 @@ namespace urde {
namespace { namespace {
logvisor::Module Log("urde::CTextureBoo"); logvisor::Module Log("urde::CTextureBoo");
struct RGBA8 {
u8 r;
u8 g;
u8 b;
u8 a;
};
/* GX uses this upsampling technique to extract full 8-bit range */ /* GX uses this upsampling technique to extract full 8-bit range */
constexpr u8 Convert3To8(u8 v) { constexpr u8 Convert3To8(u8 v) {
/* Swizzle bits: 00000123 -> 12312312 */ /* Swizzle bits: 00000123 -> 12312312 */

View File

@ -1,58 +1,71 @@
#include "Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp" #include "Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp"
#include "Runtime/Graphics/CBooRenderer.hpp" #include "Runtime/Graphics/CBooRenderer.hpp"
#include "Runtime/Graphics/CTexture.hpp"
#include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CGraphics.hpp"
#define WARP_RAMP_RES 32 #include "CSpaceWarpFilter.cpp.hshhead"
namespace urde { namespace urde {
using namespace hsh::pipeline;
void CSpaceWarpFilter::GenerateWarpRampTex(boo::IGraphicsDataFactory::Context& ctx) { struct CSpaceWarpFilterPipeline
std::array<std::array<std::array<u8, 4>, WARP_RAMP_RES + 1>, WARP_RAMP_RES + 1> data{}; : pipeline<topology<hsh::TriangleStrip>,
const float halfRes = WARP_RAMP_RES / 2.f; color_attachment<hsh::One, hsh::Zero, hsh::Add, hsh::One, hsh::Zero, hsh::Add,
for (int y = 0; y < WARP_RAMP_RES + 1; ++y) { hsh::ColorComponentFlags(hsh::CC_Red | hsh::CC_Green | hsh::CC_Blue)>,
for (int x = 0; x < WARP_RAMP_RES + 1; ++x) { depth_write<false>> {
zeus::CVector2f vec((x - halfRes) / halfRes, (y - halfRes) / halfRes); CSpaceWarpFilterPipeline(hsh::vertex_buffer<CSpaceWarpFilter::Vert> vbo,
const float mag = vec.magnitude(); hsh::uniform_buffer<CSpaceWarpFilter::Uniform> ubo, hsh::render_texture2d sceneTex,
if (mag < 1.f && vec.canBeNormalized()) { hsh::texture2d indTex) {
vec.normalize(); this->position = ubo->m_matrix * hsh::float4(vbo->m_pos, 0.f, 1.f);
vec *= zeus::CVector2f(std::sqrt(mag)); hsh::float2 sceneUv = vbo->m_pos * hsh::float2(0.5f) + hsh::float2(0.5f);
} sceneUv.y = 1.f - sceneUv.y;
data[y][x][3] = zeus::clamp(0, int((((vec.x() / 2.f + 0.5f) - x / float(WARP_RAMP_RES)) + 0.5f) * 255), 255); hsh::float2 indUv = (hsh::float3x3(ubo->m_indXf[0].xyz(), ubo->m_indXf[1].xyz(), ubo->m_indXf[2].xyz()) *
data[y][x][2] = zeus::clamp(0, int((((vec.y() / 2.f + 0.5f) - y / float(WARP_RAMP_RES)) + 0.5f) * 255), 255); hsh::float3(vbo->m_uv, 1.f))
data[y][x][0] = data[y][x][1] = data[y][x][2]; .xy();
} indUv.y = 1.f - indUv.y;
hsh::float2 indUvSample = indTex.sample<float>(indUv).xy() * hsh::float2(2.f) - hsh::float2(1.f - 1.f / 256.f);
this->color_out[0] = hsh::float4(sceneTex.sample<float>(sceneUv + indUvSample + ubo->m_strength.xy()).xyz(), 1.f);
} }
};
void CSpaceWarpFilter::GenerateWarpRampTex() {
constexpr int skWarpRampSize = 32;
m_warpTex = m_warpTex =
ctx.newStaticTexture(WARP_RAMP_RES + 1, WARP_RAMP_RES + 1, 1, boo::TextureFormat::RGBA8, hsh::create_texture2d({skWarpRampSize, skWarpRampSize}, hsh::RGBA8_UNORM, 1, [&](void* data, std::size_t size) {
boo::TextureClampMode::Repeat, data.data(), (WARP_RAMP_RES + 1) * (WARP_RAMP_RES + 1) * 4) auto* buf = static_cast<CTexture::RGBA8*>(data);
.get(); const float halfRes = skWarpRampSize / 2.f;
for (int y = 0; y < skWarpRampSize + 1; ++y) {
for (int x = 0; x < skWarpRampSize + 1; ++x) {
zeus::CVector2f vec((x - halfRes) / halfRes, (y - halfRes) / halfRes);
const float mag = vec.magnitude();
if (mag < 1.f && vec.canBeNormalized()) {
vec.normalize();
vec *= zeus::CVector2f(std::sqrt(mag));
}
auto& pixel = buf[y * skWarpRampSize + x];
pixel.a = zeus::clamp(0, int((((vec.x() / 2.f + 0.5f) - x / float(skWarpRampSize)) + 0.5f) * 255), 255);
pixel.r = pixel.g = pixel.b =
zeus::clamp(0, int((((vec.y() / 2.f + 0.5f) - y / float(skWarpRampSize)) + 0.5f) * 255), 255);
}
}
});
} }
CSpaceWarpFilter::CSpaceWarpFilter() { CSpaceWarpFilter::CSpaceWarpFilter() {
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { GenerateWarpRampTex();
GenerateWarpRampTex(ctx);
const std::array<Vert, 4> verts{{ constexpr std::array<Vert, 4> verts{{
{{-1.f, -1.f}, {0.f, 0.f}}, {{-1.f, -1.f}, {0.f, 0.f}},
{{-1.f, 1.f}, {0.f, 1.f}}, {{-1.f, 1.f}, {0.f, 1.f}},
{{1.f, -1.f}, {1.f, 0.f}}, {{1.f, -1.f}, {1.f, 0.f}},
{{1.f, 1.f}, {1.f, 1.f}}, {{1.f, 1.f}, {1.f, 1.f}},
}}; }};
m_vbo = hsh::create_vertex_buffer(verts);
m_uniBuf = hsh::create_dynamic_uniform_buffer<Uniform>();
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), 32, verts.size()); m_dataBind.hsh_bind(
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); CSpaceWarpFilterPipeline(m_vbo.get(), m_uniBuf.get(), CGraphics::g_SpareTexture.get_color(0), m_warpTex.get()));
const std::array<boo::ObjToken<boo::IGraphicsBuffer>, 1> bufs{m_uniBuf.get()};
constexpr std::array<boo::PipelineStage, 1> stages{boo::PipelineStage::Vertex};
const std::array<boo::ObjToken<boo::ITexture>, 2> texs{
CGraphics::g_SpareTexture.get(),
m_warpTex.get(),
};
m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, bufs.size(), bufs.data(),
stages.data(), nullptr, nullptr, texs.size(), texs.data(), nullptr, nullptr);
return true;
} BooTrace);
} }
void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) { void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) {
@ -117,15 +130,15 @@ void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) {
m_uniform.m_matrix[1][1] = clipRect.x10_height / vp.y(); m_uniform.m_matrix[1][1] = clipRect.x10_height / vp.y();
m_uniform.m_matrix[3][0] = pt.x() + (1.f / vp.x()); m_uniform.m_matrix[3][0] = pt.x() + (1.f / vp.x());
m_uniform.m_matrix[3][1] = pt.y() + (1.f / vp.y()); m_uniform.m_matrix[3][1] = pt.y() + (1.f / vp.y());
if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) { // if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) {
m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f; // m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f;
} else if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::Vulkan) { // } else if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::Vulkan) {
m_uniform.m_matrix[1][1] *= -1.f; // m_uniform.m_matrix[1][1] *= -1.f;
m_uniform.m_matrix[3][1] *= -1.f; // m_uniform.m_matrix[3][1] *= -1.f;
m_uniform.m_matrix[3][2] = pt.z(); // m_uniform.m_matrix[3][2] = pt.z();
} else { // } else {
m_uniform.m_matrix[3][2] = pt.z(); m_uniform.m_matrix[3][2] = pt.z();
} // }
if (clipRect.x4_left) { if (clipRect.x4_left) {
clipRect.x4_left -= 1; clipRect.x4_left -= 1;
@ -145,13 +158,12 @@ void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) {
clipRect.x8_top = g_Viewport.xc_height - clipRect.x10_height - clipRect.x8_top; clipRect.x8_top = g_Viewport.xc_height - clipRect.x10_height - clipRect.x8_top;
CGraphics::ResolveSpareTexture(clipRect); CGraphics::ResolveSpareTexture(clipRect);
m_uniform.m_strength.x() = m_uniform.m_strength.x =
m_uniform.m_matrix[0][0] * m_strength * 0.5f * (clipRect.x10_height / float(clipRect.xc_width)); m_uniform.m_matrix[0][0] * m_strength * 0.5f * (clipRect.x10_height / float(clipRect.xc_width));
m_uniform.m_strength.y() = m_uniform.m_matrix[1][1] * m_strength * 0.5f; m_uniform.m_strength.y = m_uniform.m_matrix[1][1] * m_strength * 0.5f;
m_uniBuf->load(&m_uniform, sizeof(m_uniform)); m_uniBuf.load(m_uniform);
CGraphics::SetShaderDataBinding(m_dataBind); m_dataBind.draw(0, 4);
CGraphics::DrawArray(0, 4);
} }
} // namespace urde } // namespace urde

View File

@ -9,6 +9,7 @@
namespace urde { namespace urde {
class CSpaceWarpFilter { class CSpaceWarpFilter {
public:
struct Uniform { struct Uniform {
hsh::float4x4 m_matrix; hsh::float4x4 m_matrix;
hsh::float4x4 m_indXf; hsh::float4x4 m_indXf;
@ -18,6 +19,8 @@ class CSpaceWarpFilter {
hsh::float2 m_pos; hsh::float2 m_pos;
hsh::float2 m_uv; hsh::float2 m_uv;
}; };
private:
std::array<std::array<std::array<u8, 4>, 8>, 4> m_shiftTexture{}; std::array<std::array<std::array<u8, 4>, 8>, 4> m_shiftTexture{};
hsh::owner<hsh::texture2d> m_warpTex; hsh::owner<hsh::texture2d> m_warpTex;
hsh::owner<hsh::vertex_buffer<Vert>> m_vbo; hsh::owner<hsh::vertex_buffer<Vert>> m_vbo;

View File

@ -4,50 +4,62 @@
#include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/Graphics/CTexture.hpp" #include "Runtime/Graphics/CTexture.hpp"
#include "zeus/CVector2f.hpp"
#include "CXRayBlurFilter.cpp.hshhead" #include "CXRayBlurFilter.cpp.hshhead"
namespace urde { namespace urde {
using namespace hsh::pipeline; using namespace hsh::pipeline;
struct CXRayBlurFilterPipeline : pipeline<color_attachment<>> { struct CXRayBlurFilterPipeline
: pipeline<topology<hsh::TriangleStrip>,
color_attachment<hsh::One, hsh::Zero, hsh::Add, hsh::One, hsh::Zero, hsh::Add,
hsh::ColorComponentFlags(hsh::CC_Red | hsh::CC_Green | hsh::CC_Blue)>,
depth_write<false>> {
CXRayBlurFilterPipeline(hsh::vertex_buffer<CXRayBlurFilter::Vert> vbo, CXRayBlurFilterPipeline(hsh::vertex_buffer<CXRayBlurFilter::Vert> vbo,
hsh::uniform_buffer<CXRayBlurFilter::Uniform> ubo, hsh::uniform_buffer<CXRayBlurFilter::Uniform> ubo, hsh::render_texture2d sceneTex,
hsh::render_texture2d sceneTex, hsh::texture2d paletteTex) { hsh::texture2d paletteTex) {
hsh::float2 uv0 = (ubo->m_uv[0] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv0 = (ubo->m_uv[0] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
hsh::float2 uv1 = (ubo->m_uv[1] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv1 = (ubo->m_uv[1] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
hsh::float2 uv2 = (ubo->m_uv[2] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv2 = (ubo->m_uv[2] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
hsh::float2 uv3 = (ubo->m_uv[3] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv3 = (ubo->m_uv[3] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
hsh::float2 uv4 = (ubo->m_uv[4] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv4 = (ubo->m_uv[4] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
hsh::float2 uv5 = (ubo->m_uv[5] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv5 = (ubo->m_uv[5] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
hsh::float2 uv6 = (ubo->m_uv[6] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv6 = (ubo->m_uv[6] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
hsh::float2 uv7 = (ubo->m_uv[7] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); hsh::float2 uv7 = (ubo->m_uv[7] * hsh::float4(vbo->m_uv, 0.f, 1.f)).xy();
position = hsh::float4(vbo->m_pos, 1.0); position = hsh::float4(vbo->m_pos, 0.f, 1.f);
hsh::float4 colorSample = paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv0), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; hsh::float4 kRGBToYPrime{0.257f, 0.504f, 0.098f, 0.f};
colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv1), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; hsh::float2 uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv0), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv2), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; hsh::float4 colorSample = paletteTex.sample<float>(uvSample) * 0.125f;
colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv3), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv1), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv4), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; colorSample += paletteTex.sample<float>(uvSample) * 0.125f;
colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv5), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv2), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv6), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; colorSample += paletteTex.sample<float>(uvSample) * 0.125f;
colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv7), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv3), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample<float>(uvSample) * 0.125f;
uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv4), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample<float>(uvSample) * 0.125f;
uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv5), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample<float>(uvSample) * 0.125f;
uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv6), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample<float>(uvSample) * 0.125f;
uvSample = hsh::float2(hsh::dot(sceneTex.sample<float>(uv7), kRGBToYPrime) * 0.98f + 0.01f, 0.5f);
colorSample += paletteTex.sample<float>(uvSample) * 0.125f;
color_out[0] = colorSample; color_out[0] = colorSample;
} }
}; };
CXRayBlurFilter::CXRayBlurFilter(TLockedToken<CTexture>& tex) : m_paletteTex(tex) { CXRayBlurFilter::CXRayBlurFilter(TLockedToken<CTexture>& tex) : m_paletteTex(tex) {
const std::array<Vert, 4> verts{{ constexpr std::array<Vert, 4> verts{{
{{-1.f, -1.f}, {0.f, 0.f}}, {{-1.f, -1.f}, {0.f, 0.f}},
{{-1.f, 1.f}, {0.f, 1.f}}, {{-1.f, 1.f}, {0.f, 1.f}},
{{1.f, -1.f}, {1.f, 0.f}}, {{1.f, -1.f}, {1.f, 0.f}},
{{1.f, 1.f}, {1.f, 1.f}}, {{1.f, 1.f}, {1.f, 1.f}},
}}; }};
m_vbo = hsh::create_vertex_buffer<Vert, 4>(verts); m_vbo = hsh::create_vertex_buffer<Vert, 4>(verts);
m_uniBuf = hsh::create_dynamic_uniform_buffer<Uniform>(); m_uniBuf = hsh::create_dynamic_uniform_buffer<Uniform>();
m_dataBind = hsh_binding(CXRayBlurFilterPipeline(m_vbo.get(), m_uniBuf.get(), CGraphics::g_SpareTexture.get_color(0), hsh::texture2d paletteTex = m_paletteTex->GetPaletteTexture();
m_paletteTex->GetPaletteTexture())); m_dataBind.hsh_bind(
CXRayBlurFilterPipeline(m_vbo.get(), m_uniBuf.get(), CGraphics::g_SpareTexture.get_color(0), paletteTex));
} }
void CXRayBlurFilter::draw(float amount) { void CXRayBlurFilter::draw(float amount) {