From 1e6fdbee6fd2591e9c8d0acd9dfaf26c79f659c3 Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Sun, 20 Aug 2023 11:51:49 -0400 Subject: [PATCH] [jak2] Fix depth testing issues on glow sprites (#2923) https://github.com/open-goal/jak-project/assets/48171810/0d3064f9-3f27-4be1-b6a4-55fdfb681313 Fixes https://github.com/open-goal/jak-project/issues/2328 --- game/graphics/opengl_renderer/Shader.cpp | 2 + game/graphics/opengl_renderer/Shader.h | 2 + .../shaders/glow_depth_copy.frag | 17 ++ .../shaders/glow_depth_copy.vert | 13 ++ .../shaders/glow_probe_on_grid.frag | 9 + .../shaders/glow_probe_on_grid.vert | 11 + .../opengl_renderer/sprite/GlowRenderer.cpp | 193 ++++++++++++++---- .../opengl_renderer/sprite/GlowRenderer.h | 15 +- .../opengl_renderer/sprite/Sprite3.cpp | 3 +- .../opengl_renderer/sprite/Sprite3_Glow.cpp | 14 +- 10 files changed, 236 insertions(+), 43 deletions(-) create mode 100644 game/graphics/opengl_renderer/shaders/glow_depth_copy.frag create mode 100644 game/graphics/opengl_renderer/shaders/glow_depth_copy.vert create mode 100644 game/graphics/opengl_renderer/shaders/glow_probe_on_grid.frag create mode 100644 game/graphics/opengl_renderer/shaders/glow_probe_on_grid.vert diff --git a/game/graphics/opengl_renderer/Shader.cpp b/game/graphics/opengl_renderer/Shader.cpp index 12221d82b6..83e14a03da 100644 --- a/game/graphics/opengl_renderer/Shader.cpp +++ b/game/graphics/opengl_renderer/Shader.cpp @@ -126,6 +126,8 @@ ShaderLibrary::ShaderLibrary(GameVersion version) { at(ShaderId::ETIE) = {"etie", version}; at(ShaderId::SHADOW2) = {"shadow2", version}; at(ShaderId::TEX_ANIM) = {"tex_anim", version}; + at(ShaderId::GLOW_DEPTH_COPY) = {"glow_depth_copy", version}; + at(ShaderId::GLOW_PROBE_ON_GRID) = {"glow_probe_on_grid", version}; for (auto& shader : m_shaders) { ASSERT_MSG(shader.okay(), "error compiling shader"); diff --git a/game/graphics/opengl_renderer/Shader.h b/game/graphics/opengl_renderer/Shader.h index 53fbff6372..18a07cfc50 100644 --- a/game/graphics/opengl_renderer/Shader.h +++ b/game/graphics/opengl_renderer/Shader.h @@ -59,6 +59,8 @@ enum class ShaderId { SHADOW2 = 32, DIRECT_BASIC_TEXTURED_MULTI_UNIT = 33, TEX_ANIM = 34, + GLOW_DEPTH_COPY = 35, + GLOW_PROBE_ON_GRID = 36, MAX_SHADERS }; diff --git a/game/graphics/opengl_renderer/shaders/glow_depth_copy.frag b/game/graphics/opengl_renderer/shaders/glow_depth_copy.frag new file mode 100644 index 0000000000..6aecbd3d97 --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/glow_depth_copy.frag @@ -0,0 +1,17 @@ +#version 410 core + +out vec4 out_color; + +uniform sampler2D tex; + +in vec2 tex_coord; + +void main() { + vec2 texture_coords = vec2(tex_coord.x, tex_coord.y); + out_color = vec4(0, 0, 0, 0); + if (texture_coords.x < 0 || texture_coords.x > 1 || texture_coords.y > 1 || texture_coords.x < 0) { + gl_FragDepth = 1; + } else { + gl_FragDepth = texture(tex, texture_coords).r; + } +} diff --git a/game/graphics/opengl_renderer/shaders/glow_depth_copy.vert b/game/graphics/opengl_renderer/shaders/glow_depth_copy.vert new file mode 100644 index 0000000000..f8820650ad --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/glow_depth_copy.vert @@ -0,0 +1,13 @@ +#version 410 core + +layout (location = 0) in vec4 position_in; +layout (location = 1) in vec4 rgba_in; +layout (location = 2) in vec2 uv; + +out vec2 tex_coord; + +void main() { + gl_Position = vec4((position_in.xy * 2) - 1.f, 0.f, 1.f); + tex_coord.x = uv.x / 512; + tex_coord.y = 1.f - (uv.y / SCISSOR_HEIGHT); +} diff --git a/game/graphics/opengl_renderer/shaders/glow_probe_on_grid.frag b/game/graphics/opengl_renderer/shaders/glow_probe_on_grid.frag new file mode 100644 index 0000000000..389a665a5c --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/glow_probe_on_grid.frag @@ -0,0 +1,9 @@ +#version 410 core + +out vec4 color; + +in vec4 fragment_color; + +void main() { + color = fragment_color; +} diff --git a/game/graphics/opengl_renderer/shaders/glow_probe_on_grid.vert b/game/graphics/opengl_renderer/shaders/glow_probe_on_grid.vert new file mode 100644 index 0000000000..11604d2d68 --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/glow_probe_on_grid.vert @@ -0,0 +1,11 @@ +#version 410 core + +layout (location = 0) in vec4 position_in; +// layout (location = 1) in vec4 rgba_in; + +out vec4 fragment_color; + +void main() { + gl_Position = vec4((position_in.xy * 2) - 1.f, (position_in.z / 8388608.f) - 1.f, 1.f); + fragment_color = vec4(0, 0.5, 1, 1); +} \ No newline at end of file diff --git a/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp b/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp index 589e2c28ea..0f837196c4 100644 --- a/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp +++ b/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp @@ -182,17 +182,20 @@ GlowRenderer::GlowRenderer() { glGenFramebuffers(1, &m_ogl.probe_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.probe_fbo); glGenTextures(1, &m_ogl.probe_fbo_rgba_tex); + glGenTextures(1, &m_ogl.probe_fbo_depth_tex); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_rgba_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glGenRenderbuffers(1, &m_ogl.probe_fbo_zbuf_rb); - glBindRenderbuffer(GL_RENDERBUFFER, m_ogl.probe_fbo_zbuf_rb); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - m_ogl.probe_fbo_zbuf_rb); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ogl.probe_fbo_rgba_tex, 0); + + glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_depth_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h, 0, + GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, + m_ogl.probe_fbo_depth_tex, 0); + GLenum render_targets[1] = {GL_COLOR_ATTACHMENT0}; glDrawBuffers(1, render_targets); auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -210,6 +213,15 @@ GlowRenderer::GlowRenderer() { glBindTexture(GL_TEXTURE_2D, m_ogl.downsample_fbos[i].tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ds_size * kDownsampleBatchWidth, ds_size * kDownsampleBatchWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + + if (i == 0) { + glGenRenderbuffers(1, &m_ogl.first_ds_depth_rb); + glBindRenderbuffer(GL_RENDERBUFFER, m_ogl.first_ds_depth_rb); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ds_size * kDownsampleBatchWidth, + ds_size * kDownsampleBatchWidth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + m_ogl.first_ds_depth_rb); + } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ogl.downsample_fbos[i].tex, 0); glDrawBuffers(1, render_targets); @@ -234,6 +246,8 @@ GlowRenderer::GlowRenderer() { // ;; (new 'static 'gs-zbuf :zbp 304 :psm 1 :zmsk 1) // (new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-1) :x #x1000130 :y #x1) m_default_draw_mode.disable_depth_write(); + + glGenTextures(1, &m_ogl.depth_texture); } namespace { @@ -361,6 +375,48 @@ void GlowRenderer::add_sprite_pass_2(const SpriteGlowOutput& data, int sprite_id idx[4] = UINT32_MAX; } +void GlowRenderer::add_sprite_new(const SpriteGlowOutput& data, int sprite_idx) { + // output is a grid of kBatchWidth * kBatchWidth. + // for simplicity, we'll map to (0, 1) here, and the shader will convert to (-1, 1) for opengl. + int x = sprite_idx / kDownsampleBatchWidth; + int y = sprite_idx % kDownsampleBatchWidth; + float step = 1.f / kDownsampleBatchWidth; + + u32 idx_start = m_next_vertex; + Vertex* vtx = alloc_vtx(4); + for (int i = 0; i < 4; i++) { + vtx[i].r = 1.f; // debug + vtx[i].g = 0.f; + vtx[i].b = 0.f; + vtx[i].a = 0.f; + vtx[i].x = x * step; // start of our cell + vtx[i].y = y * step; + vtx[i].z = data.second_clear_pos[0].z(); + vtx[i].w = 0; + } + vtx[1].x += step; + vtx[2].y += step; + vtx[3].x += step; + vtx[3].y += step; + + // transformation code gives us these coordinates for where to sample probe fbo + vtx[0].u = data.offscreen_uv[0][0]; + vtx[0].v = data.offscreen_uv[0][1]; + vtx[1].u = data.offscreen_uv[1][0]; + vtx[1].v = data.offscreen_uv[0][1]; + vtx[2].u = data.offscreen_uv[0][0]; + vtx[2].v = data.offscreen_uv[1][1]; + vtx[3].u = data.offscreen_uv[1][0]; + vtx[3].v = data.offscreen_uv[1][1]; + + u32* idx = alloc_index(5); + idx[0] = idx_start; + idx[1] = idx_start + 1; + idx[2] = idx_start + 2; + idx[3] = idx_start + 3; + idx[4] = UINT32_MAX; +} + /*! * Add pass 3 vertices and update sprite records. This is the final draw. */ @@ -469,9 +525,10 @@ void GlowRenderer::blit_depth(SharedRenderState* render_state) { GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); - glBindRenderbuffer(GL_RENDERBUFFER, m_ogl.probe_fbo_zbuf_rb); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_ogl.probe_fbo_w, - m_ogl.probe_fbo_h); + glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_depth_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h, 0, + GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glBindTexture(GL_TEXTURE_2D, 0); } glBindFramebuffer(GL_READ_FRAMEBUFFER, render_state->render_fb); @@ -509,6 +566,8 @@ void GlowRenderer::downsample_chain(SharedRenderState* render_state, GLint old_viewport[4]; glGetIntegerv(GL_VIEWPORT, old_viewport); render_state->shaders[ShaderId::GLOW_PROBE_DOWNSAMPLE].activate(); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); for (int i = 0; i < kDownsampleIterations - 1; i++) { auto* source = &m_ogl.downsample_fbos[i]; auto* dest = &m_ogl.downsample_fbos[i + 1]; @@ -528,6 +587,21 @@ void GlowRenderer::downsample_chain(SharedRenderState* render_state, glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]); } +void GlowRenderer::setup_buffers_for_draws() { + glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.probe_fbo); + glBindVertexArray(m_ogl.vao); + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(UINT32_MAX); + // don't want to write to the depth buffer we just copied, just test against it. + glDepthMask(GL_FALSE); + glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, m_next_vertex * sizeof(Vertex), m_vertex_buffer.data(), + GL_STREAM_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_index * sizeof(u32), m_index_buffer.data(), + GL_STREAM_DRAW); +} + /*! * Draw probes (including the clear) to the probe fbo. Also copies vertex/index buffer. */ @@ -535,24 +609,10 @@ void GlowRenderer::draw_probes(SharedRenderState* render_state, ScopedProfilerNode& prof, u32 idx_start, u32 idx_end) { - glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.probe_fbo); - glBindVertexArray(m_ogl.vao); - glEnable(GL_PRIMITIVE_RESTART); - glPrimitiveRestartIndex(UINT32_MAX); - // don't want to write to the depth buffer we just copied, just test against it. - glDepthMask(GL_FALSE); + render_state->shaders[ShaderId::GLOW_PROBE].activate(); GLint old_viewport[4]; glGetIntegerv(GL_VIEWPORT, old_viewport); glViewport(0, 0, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h); - glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, m_next_vertex * sizeof(Vertex), m_vertex_buffer.data(), - GL_STREAM_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_index * sizeof(u32), m_index_buffer.data(), - GL_STREAM_DRAW); - - // do probes - render_state->shaders[ShaderId::GLOW_PROBE].activate(); prof.add_draw_call(); prof.add_tri(m_next_sprite * 4); glDisable(GL_BLEND); @@ -589,6 +649,7 @@ void GlowRenderer::draw_probe_copies(SharedRenderState* render_state, glGetIntegerv(GL_VIEWPORT, old_viewport); render_state->shaders[ShaderId::GLOW_PROBE_READ].activate(); glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.downsample_fbos[0].fbo); + glDisable(GL_DEPTH_TEST); glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_rgba_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -617,20 +678,7 @@ void GlowRenderer::debug_draw_probe_copies(SharedRenderState* render_state, (void*)(idx_start * sizeof(u32))); } -/*! - * Draw all pending sprites. - */ -void GlowRenderer::flush(SharedRenderState* render_state, ScopedProfilerNode& prof) { - m_debug.num_sprites = m_next_sprite; - if (!m_next_sprite) { - // no sprites submitted. - return; - } - - // copy depth from framebuffer to a temporary buffer - // (this is a bit wasteful) - blit_depth(render_state); - +void GlowRenderer::probe_and_copy_old(SharedRenderState* render_state, ScopedProfilerNode& prof) { // generate vertex/index data for probes u32 probe_idx_start = m_next_index; for (u32 sidx = 0; sidx < m_next_sprite; sidx++) { @@ -650,6 +698,7 @@ void GlowRenderer::flush(SharedRenderState* render_state, ScopedProfilerNode& pr } // draw probes + setup_buffers_for_draws(); draw_probes(render_state, prof, probe_idx_start, copy_idx_start); if (m_debug.show_probes) { debug_draw_probes(render_state, prof, probe_idx_start, copy_idx_start); @@ -660,6 +709,76 @@ void GlowRenderer::flush(SharedRenderState* render_state, ScopedProfilerNode& pr if (m_debug.show_probe_copies) { debug_draw_probe_copies(render_state, prof, copy_idx_start, copy_idx_end); } +} + +void GlowRenderer::probe_and_copy_new(SharedRenderState* render_state, ScopedProfilerNode& prof) { + u32 idx_start = m_next_index; + for (u32 sidx = 0; sidx < m_next_sprite; sidx++) { + add_sprite_new(m_sprite_data_buffer[sidx], sidx); + } + u32 idx_end = m_next_index; + + // generate vertex/index data for framebuffer draws + for (u32 sidx = 0; sidx < m_next_sprite; sidx++) { + add_sprite_pass_3(m_sprite_data_buffer[sidx], sidx); + } + + // clear the grid. + setup_buffers_for_draws(); + GLint old_viewport[4]; + glGetIntegerv(GL_VIEWPORT, old_viewport); + render_state->shaders[ShaderId::GLOW_PROBE_READ].activate(); + glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.downsample_fbos[0].fbo); + glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_depth_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glViewport(0, 0, m_ogl.downsample_fbos[0].size, m_ogl.downsample_fbos[0].size); + + // TODO: can probably remove this clear + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); + + render_state->shaders[ShaderId::GLOW_DEPTH_COPY].activate(); + prof.add_draw_call(); + prof.add_tri(m_next_sprite * 2); + glDrawElements(GL_TRIANGLE_STRIP, idx_end - idx_start, GL_UNSIGNED_INT, + (void*)(idx_start * sizeof(u32))); + + render_state->shaders[ShaderId::GLOW_PROBE_ON_GRID].activate(); + glDepthFunc(GL_GREATER); + prof.add_draw_call(); + prof.add_tri(m_next_sprite * 2); + glDrawElements(GL_TRIANGLE_STRIP, idx_end - idx_start, GL_UNSIGNED_INT, + (void*)(idx_start * sizeof(u32))); + + glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]); +} + +/*! + * Draw all pending sprites. + */ +void GlowRenderer::flush(SharedRenderState* render_state, ScopedProfilerNode& prof) { + m_debug.num_sprites = m_next_sprite; + if (!m_next_sprite) { + // no sprites submitted. + return; + } + + // copy depth from framebuffer to a temporary buffer + // (this is a bit wasteful) + blit_depth(render_state); + + if (new_mode) { + probe_and_copy_new(render_state, prof); + } else { + probe_and_copy_old(render_state, prof); + } // downsample probes. downsample_chain(render_state, prof, m_next_sprite); diff --git a/game/graphics/opengl_renderer/sprite/GlowRenderer.h b/game/graphics/opengl_renderer/sprite/GlowRenderer.h index a3ba19734b..ed00367703 100644 --- a/game/graphics/opengl_renderer/sprite/GlowRenderer.h +++ b/game/graphics/opengl_renderer/sprite/GlowRenderer.h @@ -11,6 +11,8 @@ class GlowRenderer { void flush(SharedRenderState* render_state, ScopedProfilerNode& prof); void draw_debug_window(); + bool new_mode = true; + // Vertex can hold all possible values for all passes. The total number of vertices is very small // so it ends up a lot faster to do a single upload, even if the size is like 50% larger than it // could be. @@ -32,8 +34,15 @@ class GlowRenderer { void add_sprite_pass_2(const SpriteGlowOutput& data, int sprite_idx); void add_sprite_pass_3(const SpriteGlowOutput& data, int sprite_idx); + void add_sprite_new(const SpriteGlowOutput& data, int sprite_idx); + + void probe_and_copy_old(SharedRenderState* render_state, ScopedProfilerNode& prof); + void probe_and_copy_new(SharedRenderState* render_state, ScopedProfilerNode& prof); + void blit_depth(SharedRenderState* render_state); + void setup_buffers_for_draws(); + void draw_probes(SharedRenderState* render_state, ScopedProfilerNode& prof, u32 idx_start, @@ -91,10 +100,14 @@ class GlowRenderer { GLuint probe_fbo; GLuint probe_fbo_rgba_tex; - GLuint probe_fbo_zbuf_rb; + GLuint probe_fbo_depth_tex; + GLuint first_ds_depth_rb; + // GLuint probe_fbo_zbuf_rb; int probe_fbo_w = 640; int probe_fbo_h = 480; + GLuint depth_texture; + DsFbo downsample_fbos[kDownsampleIterations]; } m_ogl; diff --git a/game/graphics/opengl_renderer/sprite/Sprite3.cpp b/game/graphics/opengl_renderer/sprite/Sprite3.cpp index 7d30c59aba..a6bab3efc9 100644 --- a/game/graphics/opengl_renderer/sprite/Sprite3.cpp +++ b/game/graphics/opengl_renderer/sprite/Sprite3.cpp @@ -550,6 +550,8 @@ void Sprite3::render_jak1(DmaFollower& dma, } void Sprite3::draw_debug_window() { + ImGui::Checkbox("Glow", &m_enable_glow); + ImGui::Checkbox("new glow", &m_glow_renderer.new_mode); ImGui::Separator(); ImGui::Text("Distort sprites: %d", m_distort_stats.total_sprites); ImGui::Text("2D Group 0 (World) blocks: %d sprites: %d", m_debug_stats.blocks_2d_grp0, @@ -558,7 +560,6 @@ void Sprite3::draw_debug_window() { m_debug_stats.count_2d_grp1); ImGui::Checkbox("Culling", &m_enable_culling); ImGui::Checkbox("2d", &m_2d_enable); - ImGui::Checkbox("Glow", &m_enable_glow); ImGui::SameLine(); ImGui::Checkbox("3d", &m_3d_enable); ImGui::Checkbox("Distort", &m_distort_enable); diff --git a/game/graphics/opengl_renderer/sprite/Sprite3_Glow.cpp b/game/graphics/opengl_renderer/sprite/Sprite3_Glow.cpp index da5665a8f6..d10c227370 100644 --- a/game/graphics/opengl_renderer/sprite/Sprite3_Glow.cpp +++ b/game/graphics/opengl_renderer/sprite/Sprite3_Glow.cpp @@ -27,6 +27,7 @@ static_assert(sizeof(SpriteGlowData) == 16 * 4); * small, so not a big deal. */ bool glow_math(const SpriteGlowConsts* consts, + bool skip_uv_clamp, const void* vec_data, const void* adgif_data, SpriteGlowOutput* out) { @@ -137,9 +138,14 @@ bool glow_math(const SpriteGlowConsts* consts, // max.xy vf20, vf01, vf09 -> is this bugged? I think the x broadcast here is wrong // this breaks fadeout as the sprite moves off the top of the screen. I've fixed it here because // I'm pretty sure this is just a mistake. - math::Vector2f vf20_pos(std::max(p0.x(), vf09_min_probe_center.x()), - std::max(p0.y(), vf09_min_probe_center.y())); - vf20_pos.min_in_place(vf10_max_probe_center); + math::Vector2f vf20_pos; + if (skip_uv_clamp) { + vf20_pos = p0.xy(); + } else { + vf20_pos = math::Vector2f(std::max(p0.x(), vf09_min_probe_center.x()), + std::max(p0.y(), vf09_min_probe_center.y())); + vf20_pos.min_in_place(vf10_max_probe_center); + } // vf17 thing, vf18 thing math::Vector2f vf17(consts->clamp_min.x() - 1, consts->clamp_min.y() - 1); @@ -215,7 +221,7 @@ void Sprite3::glow_dma_and_draw(DmaFollower& dma, if (m_enable_glow) { auto* out = m_glow_renderer.alloc_sprite(); - if (!glow_math(&consts, vecdata_xfer.data, shader_xfer.data, out)) { + if (!glow_math(&consts, m_glow_renderer.new_mode, vecdata_xfer.data, shader_xfer.data, out)) { m_glow_renderer.cancel_sprite(); } }