diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index 785ca6782..55daab520 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -70,4 +70,6 @@ runtime_add_hsh(Graphics Shaders/CRadarPaintShader.cpp Shaders/CRandomStaticFilter.cpp Shaders/CScanLinesFilter.cpp + Shaders/CSpaceWarpFilter.cpp + Shaders/CXRayBlurFilter.cpp ) diff --git a/Runtime/Graphics/CTexture.hpp b/Runtime/Graphics/CTexture.hpp index c307b163d..96a6260f5 100644 --- a/Runtime/Graphics/CTexture.hpp +++ b/Runtime/Graphics/CTexture.hpp @@ -25,6 +25,13 @@ public: TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */ }; + struct RGBA8 { + u8 r; + u8 g; + u8 b; + u8 a; + }; + private: ETexelFormat x0_fmt; u16 x4_w; diff --git a/Runtime/Graphics/CTextureBoo.cpp b/Runtime/Graphics/CTextureBoo.cpp index 702811ed6..682576e88 100644 --- a/Runtime/Graphics/CTextureBoo.cpp +++ b/Runtime/Graphics/CTextureBoo.cpp @@ -12,13 +12,6 @@ namespace urde { namespace { 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 */ constexpr u8 Convert3To8(u8 v) { /* Swizzle bits: 00000123 -> 12312312 */ diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp index adb172787..3712ed983 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp @@ -1,58 +1,71 @@ #include "Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp" #include "Runtime/Graphics/CBooRenderer.hpp" +#include "Runtime/Graphics/CTexture.hpp" #include "Runtime/Graphics/CGraphics.hpp" -#define WARP_RAMP_RES 32 +#include "CSpaceWarpFilter.cpp.hshhead" namespace urde { +using namespace hsh::pipeline; -void CSpaceWarpFilter::GenerateWarpRampTex(boo::IGraphicsDataFactory::Context& ctx) { - std::array, WARP_RAMP_RES + 1>, WARP_RAMP_RES + 1> data{}; - const float halfRes = WARP_RAMP_RES / 2.f; - for (int y = 0; y < WARP_RAMP_RES + 1; ++y) { - for (int x = 0; x < WARP_RAMP_RES + 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)); - } - data[y][x][3] = zeus::clamp(0, int((((vec.x() / 2.f + 0.5f) - x / float(WARP_RAMP_RES)) + 0.5f) * 255), 255); - data[y][x][2] = zeus::clamp(0, int((((vec.y() / 2.f + 0.5f) - y / float(WARP_RAMP_RES)) + 0.5f) * 255), 255); - data[y][x][0] = data[y][x][1] = data[y][x][2]; - } +struct CSpaceWarpFilterPipeline +: pipeline, + color_attachment, + depth_write> { + CSpaceWarpFilterPipeline(hsh::vertex_buffer vbo, + hsh::uniform_buffer ubo, hsh::render_texture2d sceneTex, + hsh::texture2d indTex) { + this->position = ubo->m_matrix * hsh::float4(vbo->m_pos, 0.f, 1.f); + hsh::float2 sceneUv = vbo->m_pos * hsh::float2(0.5f) + hsh::float2(0.5f); + sceneUv.y = 1.f - sceneUv.y; + hsh::float2 indUv = (hsh::float3x3(ubo->m_indXf[0].xyz(), ubo->m_indXf[1].xyz(), ubo->m_indXf[2].xyz()) * + hsh::float3(vbo->m_uv, 1.f)) + .xy(); + indUv.y = 1.f - indUv.y; + hsh::float2 indUvSample = indTex.sample(indUv).xy() * hsh::float2(2.f) - hsh::float2(1.f - 1.f / 256.f); + this->color_out[0] = hsh::float4(sceneTex.sample(sceneUv + indUvSample + ubo->m_strength.xy()).xyz(), 1.f); } +}; + +void CSpaceWarpFilter::GenerateWarpRampTex() { + constexpr int skWarpRampSize = 32; m_warpTex = - ctx.newStaticTexture(WARP_RAMP_RES + 1, WARP_RAMP_RES + 1, 1, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, data.data(), (WARP_RAMP_RES + 1) * (WARP_RAMP_RES + 1) * 4) - .get(); + hsh::create_texture2d({skWarpRampSize, skWarpRampSize}, hsh::RGBA8_UNORM, 1, [&](void* data, std::size_t size) { + auto* buf = static_cast(data); + 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() { - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { - GenerateWarpRampTex(ctx); + GenerateWarpRampTex(); - const std::array verts{{ - {{-1.f, -1.f}, {0.f, 0.f}}, - {{-1.f, 1.f}, {0.f, 1.f}}, - {{1.f, -1.f}, {1.f, 0.f}}, - {{1.f, 1.f}, {1.f, 1.f}}, - }}; + constexpr std::array verts{{ + {{-1.f, -1.f}, {0.f, 0.f}}, + {{-1.f, 1.f}, {0.f, 1.f}}, + {{1.f, -1.f}, {1.f, 0.f}}, + {{1.f, 1.f}, {1.f, 1.f}}, + }}; + m_vbo = hsh::create_vertex_buffer(verts); + m_uniBuf = hsh::create_dynamic_uniform_buffer(); - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), 32, verts.size()); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - - const std::array, 1> bufs{m_uniBuf.get()}; - constexpr std::array stages{boo::PipelineStage::Vertex}; - const std::array, 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); + m_dataBind.hsh_bind( + CSpaceWarpFilterPipeline(m_vbo.get(), m_uniBuf.get(), CGraphics::g_SpareTexture.get_color(0), m_warpTex.get())); } 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[3][0] = pt.x() + (1.f / vp.x()); m_uniform.m_matrix[3][1] = pt.y() + (1.f / vp.y()); - if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) { - m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f; - } else if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::Vulkan) { - m_uniform.m_matrix[1][1] *= -1.f; - m_uniform.m_matrix[3][1] *= -1.f; - m_uniform.m_matrix[3][2] = pt.z(); - } else { - m_uniform.m_matrix[3][2] = pt.z(); - } + // if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) { + // m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f; + // } else if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::Vulkan) { + // m_uniform.m_matrix[1][1] *= -1.f; + // m_uniform.m_matrix[3][1] *= -1.f; + // m_uniform.m_matrix[3][2] = pt.z(); + // } else { + m_uniform.m_matrix[3][2] = pt.z(); + // } if (clipRect.x4_left) { 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; 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_strength.y() = m_uniform.m_matrix[1][1] * m_strength * 0.5f; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + m_uniform.m_strength.y = m_uniform.m_matrix[1][1] * m_strength * 0.5f; + m_uniBuf.load(m_uniform); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + m_dataBind.draw(0, 4); } } // namespace urde diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp index 613c95933..7c94e8b38 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp @@ -9,6 +9,7 @@ namespace urde { class CSpaceWarpFilter { +public: struct Uniform { hsh::float4x4 m_matrix; hsh::float4x4 m_indXf; @@ -18,6 +19,8 @@ class CSpaceWarpFilter { hsh::float2 m_pos; hsh::float2 m_uv; }; + +private: std::array, 8>, 4> m_shiftTexture{}; hsh::owner m_warpTex; hsh::owner> m_vbo; diff --git a/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp b/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp index a3446d9b7..5804be126 100644 --- a/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp +++ b/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp @@ -4,50 +4,62 @@ #include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CTexture.hpp" -#include "zeus/CVector2f.hpp" - #include "CXRayBlurFilter.cpp.hshhead" namespace urde { using namespace hsh::pipeline; -struct CXRayBlurFilterPipeline : pipeline> { +struct CXRayBlurFilterPipeline +: pipeline, + color_attachment, + depth_write> { CXRayBlurFilterPipeline(hsh::vertex_buffer vbo, - hsh::uniform_buffer ubo, - hsh::render_texture2d sceneTex, hsh::texture2d paletteTex) { - hsh::float2 uv0 = (ubo->m_uv[0] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - hsh::float2 uv1 = (ubo->m_uv[1] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - hsh::float2 uv2 = (ubo->m_uv[2] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - hsh::float2 uv3 = (ubo->m_uv[3] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - hsh::float2 uv4 = (ubo->m_uv[4] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - hsh::float2 uv5 = (ubo->m_uv[5] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - hsh::float2 uv6 = (ubo->m_uv[6] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - hsh::float2 uv7 = (ubo->m_uv[7] * hsh::float4(vbo->m_uv, 0.0, 1.0)).xy(); - position = hsh::float4(vbo->m_pos, 1.0); + hsh::uniform_buffer ubo, hsh::render_texture2d sceneTex, + hsh::texture2d paletteTex) { + 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.f, 1.f)).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.f, 1.f)).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.f, 1.f)).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.f, 1.f)).xy(); + 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; - colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv1), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; - colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv2), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; - colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv3), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; - colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv4), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; - colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv5), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; - colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv6), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; - colorSample += paletteTex.sample(hsh::float2(hsh::dot(sceneTex.sample(uv7), kRGBToYPrime) * 0.98 + 0.01, 0.5)) * 0.125; + hsh::float4 kRGBToYPrime{0.257f, 0.504f, 0.098f, 0.f}; + hsh::float2 uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv0), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + hsh::float4 colorSample = paletteTex.sample(uvSample) * 0.125f; + uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv1), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + colorSample += paletteTex.sample(uvSample) * 0.125f; + uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv2), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + colorSample += paletteTex.sample(uvSample) * 0.125f; + uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv3), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + colorSample += paletteTex.sample(uvSample) * 0.125f; + uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv4), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + colorSample += paletteTex.sample(uvSample) * 0.125f; + uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv5), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + colorSample += paletteTex.sample(uvSample) * 0.125f; + uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv6), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + colorSample += paletteTex.sample(uvSample) * 0.125f; + uvSample = hsh::float2(hsh::dot(sceneTex.sample(uv7), kRGBToYPrime) * 0.98f + 0.01f, 0.5f); + colorSample += paletteTex.sample(uvSample) * 0.125f; color_out[0] = colorSample; } }; CXRayBlurFilter::CXRayBlurFilter(TLockedToken& tex) : m_paletteTex(tex) { - const std::array verts{{ - {{-1.f, -1.f}, {0.f, 0.f}}, - {{-1.f, 1.f}, {0.f, 1.f}}, - {{1.f, -1.f}, {1.f, 0.f}}, - {{1.f, 1.f}, {1.f, 1.f}}, - }}; + constexpr std::array verts{{ + {{-1.f, -1.f}, {0.f, 0.f}}, + {{-1.f, 1.f}, {0.f, 1.f}}, + {{1.f, -1.f}, {1.f, 0.f}}, + {{1.f, 1.f}, {1.f, 1.f}}, + }}; m_vbo = hsh::create_vertex_buffer(verts); m_uniBuf = hsh::create_dynamic_uniform_buffer(); - m_dataBind = hsh_binding(CXRayBlurFilterPipeline(m_vbo.get(), m_uniBuf.get(), CGraphics::g_SpareTexture.get_color(0), - m_paletteTex->GetPaletteTexture())); + hsh::texture2d paletteTex = 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) {