diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index ba6da7cce1..89848815ed 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -75,6 +75,7 @@ set(RUNTIME_SOURCE graphics/opengl_renderer/SkyBlendCPU.cpp graphics/opengl_renderer/SkyBlendGPU.cpp graphics/opengl_renderer/SkyRenderer.cpp + graphics/opengl_renderer/SlowTimeEffect.cpp graphics/opengl_renderer/sprite/GlowRenderer.cpp graphics/opengl_renderer/sprite/Sprite3_Distort.cpp graphics/opengl_renderer/sprite/Sprite3_Glow.cpp diff --git a/game/graphics/opengl_renderer/BlitDisplays.cpp b/game/graphics/opengl_renderer/BlitDisplays.cpp index 81930164f9..ad9aa2b863 100644 --- a/game/graphics/opengl_renderer/BlitDisplays.cpp +++ b/game/graphics/opengl_renderer/BlitDisplays.cpp @@ -76,6 +76,12 @@ void BlitDisplays::render(DmaFollower& dma, m_color_filter_pending = true; memcpy(m_color_filter.data(), data.data, sizeof(math::Vector4f)); } break; + case 0x15: { // slow-time + m_blur_old_copier.copy_now(render_state->render_fb_w, render_state->render_fb_h, + render_state->render_fb); + m_slow_time_pending = true; + memcpy(&m_slow_time_amount, data.data, sizeof(float)); + } break; } } } @@ -112,6 +118,9 @@ void BlitDisplays::do_copy_back(SharedRenderState* render_state, ScopedProfilerN } else if (m_zoom_blur_pending) { do_zoom_blur(render_state, prof); m_zoom_blur_pending = false; + } else if (m_slow_time_pending) { + do_slow_time(render_state, prof); + m_slow_time_pending = false; } } @@ -159,16 +168,37 @@ void BlitDisplays::do_zoom_blur(SharedRenderState* render_state, ScopedProfilerN glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, m_blur_old_copier.texture()); - // zoom blur draw + // draw old image m_fullscreen_tex_draw.draw(m_zoom_blur.color.cast() / 128.f, math::Vector2f{xmin, ymin}, math::Vector2f{xmax, ymax}, render_state, prof); - // screen draw + // draw new image on top of it glBindTexture(GL_TEXTURE_2D, m_blur_new_copier.texture()); m_fullscreen_tex_draw.draw(math::Vector4f{1.f, 1.f, 1.f, m_zoom_blur.alpha_current}, math::Vector2f{0, 0}, math::Vector2f{1, 1}, render_state, prof); } +void BlitDisplays::do_slow_time(SharedRenderState* render_state, ScopedProfilerNode& prof) { + m_blur_new_copier.copy_now(render_state->render_fb_w, render_state->render_fb_h, + render_state->render_fb); + + // clear screen + glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + // GL Setup + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBindTexture(GL_TEXTURE_2D, m_blur_old_copier.texture()); + + // draw old image + m_fullscreen_tex_draw.draw({1.f, 1.f, 1.f, 1.f}, math::Vector2f{0, 0}, math::Vector2f{1, 1}, + render_state, prof); + glBindTexture(GL_TEXTURE_2D, m_blur_new_copier.texture()); + m_slow_time_effect.draw(m_slow_time_amount, render_state, prof); +} + void BlitDisplays::draw_debug_window() { glBindTexture(GL_TEXTURE_2D, m_copier->texture()); int w, h; @@ -179,10 +209,15 @@ void BlitDisplays::draw_debug_window() { void BlitDisplays::apply_color_filter(SharedRenderState* render_state, ScopedProfilerNode& prof) { if (m_color_filter_pending) { - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_DST_COLOR, GL_ZERO); - m_color_draw.draw(m_color_filter, render_state, prof); + // if the multiplier is >1, the only way I see to do this is copy and redraw the whole screen. + // doing the fullscreen draw also seems to cause alpha-related issues - the debug menu + // background stops showing up. + m_blur_new_copier.copy_now(render_state->render_fb_w, render_state->render_fb_h, + render_state->render_fb); + glDisable(GL_DEPTH_TEST); + glBindTexture(GL_TEXTURE_2D, m_blur_new_copier.texture()); + m_fullscreen_tex_draw.draw(m_color_filter, math::Vector2f{0, 0}, math::Vector2f{1, 1}, + render_state, prof); m_color_filter_pending = false; } } diff --git a/game/graphics/opengl_renderer/BlitDisplays.h b/game/graphics/opengl_renderer/BlitDisplays.h index 4260d1f02c..b5b86afcda 100644 --- a/game/graphics/opengl_renderer/BlitDisplays.h +++ b/game/graphics/opengl_renderer/BlitDisplays.h @@ -1,6 +1,7 @@ #pragma once #include "game/graphics/opengl_renderer/BucketRenderer.h" +#include "game/graphics/opengl_renderer/SlowTimeEffect.h" #include "game/graphics/opengl_renderer/opengl_utils.h" #include "game/graphics/texture/TexturePool.h" @@ -23,6 +24,7 @@ class BlitDisplays : public BucketRenderer { void draw_debug_window() override; void do_copy_back(SharedRenderState* render_state, ScopedProfilerNode& prof); void do_zoom_blur(SharedRenderState* render_state, ScopedProfilerNode& prof); + void do_slow_time(SharedRenderState* render_state, ScopedProfilerNode& prof); void apply_color_filter(SharedRenderState* render_state, ScopedProfilerNode& prof); private: @@ -34,8 +36,11 @@ class BlitDisplays : public BucketRenderer { bool m_copy_back_pending = false; bool m_zoom_blur_pending = false; bool m_color_filter_pending = false; + bool m_slow_time_pending = false; + float m_slow_time_amount = 0; math::Vector4f m_color_filter; PcZoomBlur m_zoom_blur; FullScreenTexDraw m_fullscreen_tex_draw; FullScreenDraw m_color_draw; + SlowTimeEffect m_slow_time_effect; }; diff --git a/game/graphics/opengl_renderer/Shader.cpp b/game/graphics/opengl_renderer/Shader.cpp index 7ce0bf18bb..c7ba095df6 100644 --- a/game/graphics/opengl_renderer/Shader.cpp +++ b/game/graphics/opengl_renderer/Shader.cpp @@ -133,6 +133,7 @@ ShaderLibrary::ShaderLibrary(GameVersion version) { at(ShaderId::PLAIN_TEXTURE) = {"plain_texture", version}; at(ShaderId::TIE_WIND) = {"tie_wind", version}; at(ShaderId::SIMPLE_TEXTURE) = {"simple_texture", version}; + at(ShaderId::SLOW_TIME) = {"slow_time", 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 4471f31a0f..f0bf05246e 100644 --- a/game/graphics/opengl_renderer/Shader.h +++ b/game/graphics/opengl_renderer/Shader.h @@ -66,6 +66,7 @@ enum class ShaderId { PLAIN_TEXTURE = 39, TIE_WIND = 40, SIMPLE_TEXTURE = 41, + SLOW_TIME = 42, MAX_SHADERS }; diff --git a/game/graphics/opengl_renderer/SlowTimeEffect.cpp b/game/graphics/opengl_renderer/SlowTimeEffect.cpp new file mode 100644 index 0000000000..fdf30a33c6 --- /dev/null +++ b/game/graphics/opengl_renderer/SlowTimeEffect.cpp @@ -0,0 +1,68 @@ +#include "SlowTimeEffect.h" + +/* + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 2) 96 96 96 192) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 3) 4088 3320 0 0) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 4) 5120 (* arg2 8) #xffffff #x10000) + + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 5) 128 128 128 arg3) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 6) 8 8 0 0) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 7) 0 0 #xffffff 0) + + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 8) 128 128 128 arg3) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 9) 8184 8 0 0) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 10) #x2800 0 #xffffff #x10000) + + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 11) 128 128 128 arg3) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 12) 8184 (+ (* (+ arg1 -1) 16) 8) 0 0) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 13) #x2800 (* arg2 16) #xffffff #x10000) + + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 14) 128 128 128 arg3) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 15) 8 (+ (* (+ arg1 -1) 16) 8) 0 0) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 16) 0 (* arg2 16) #xffffff #x10000) + + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 17) 128 128 128 arg3) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 18) 8 8 0 0) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 19) 0 0 #xffffff 0) + */ + +SlowTimeEffect::SlowTimeEffect() { + glGenVertexArrays(1, &m_vao); + glGenBuffers(1, &m_vertex_buffer); + glBindVertexArray(m_vao); + + // mid, mid <- color is 96, 96, 96, 192 + // low, low <- color is 128, 128, 128, color + // hi, low + // hi, hi + // lo, hi + // lo, lo + + std::array vertices = {0, 1, 2, 3, 4, 5}; + + glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(int32_t) * 6, vertices.data(), GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribIPointer(0, 1, GL_INT, sizeof(int32_t), nullptr); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +SlowTimeEffect::~SlowTimeEffect() { + glDeleteVertexArrays(1, &m_vao); + glDeleteBuffers(1, &m_vertex_buffer); +} + +void SlowTimeEffect::draw(float amount, SharedRenderState* render_state, ScopedProfilerNode& prof) { + glBindVertexArray(m_vao); + glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer); + auto& shader = render_state->shaders[ShaderId::SLOW_TIME]; + shader.activate(); + glUniform1f(glGetUniformLocation(shader.id(), "amount"), amount); + + prof.add_tri(4); + prof.add_draw_call(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 6); +} diff --git a/game/graphics/opengl_renderer/SlowTimeEffect.h b/game/graphics/opengl_renderer/SlowTimeEffect.h new file mode 100644 index 0000000000..4b63ec9c61 --- /dev/null +++ b/game/graphics/opengl_renderer/SlowTimeEffect.h @@ -0,0 +1,16 @@ +#pragma once + +#include "game/graphics/opengl_renderer/BucketRenderer.h" + +class SlowTimeEffect { + public: + SlowTimeEffect(); + ~SlowTimeEffect(); + SlowTimeEffect(const SlowTimeEffect&) = delete; + SlowTimeEffect& operator=(const SlowTimeEffect&) = delete; + void draw(float amount, SharedRenderState* render_state, ScopedProfilerNode& prof); + + private: + GLuint m_vao; + GLuint m_vertex_buffer; +}; \ No newline at end of file diff --git a/game/graphics/opengl_renderer/opengl_utils.cpp b/game/graphics/opengl_renderer/opengl_utils.cpp index 88fa48583a..e576bc0d5d 100644 --- a/game/graphics/opengl_renderer/opengl_utils.cpp +++ b/game/graphics/opengl_renderer/opengl_utils.cpp @@ -159,7 +159,7 @@ FullScreenTexDraw::FullScreenTexDraw() { glGenBuffers(1, &m_vertex_buffer); glBindVertexArray(m_vao); - std::array vertices = {0, 1, 2, 4}; + std::array vertices = {0, 1, 2, 3}; glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(int32_t) * 4, vertices.data(), GL_STATIC_DRAW); diff --git a/game/graphics/opengl_renderer/shaders/slow_time.frag b/game/graphics/opengl_renderer/shaders/slow_time.frag new file mode 100644 index 0000000000..d51d273e57 --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/slow_time.frag @@ -0,0 +1,10 @@ +#version 410 core + +out vec4 out_color; +in vec2 tex; +in vec4 color; +uniform sampler2D tex_T0; + +void main() { + out_color = texture(tex_T0, tex) * color; +} \ No newline at end of file diff --git a/game/graphics/opengl_renderer/shaders/slow_time.vert b/game/graphics/opengl_renderer/shaders/slow_time.vert new file mode 100644 index 0000000000..8b12991fb6 --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/slow_time.vert @@ -0,0 +1,37 @@ +#version 410 core + +layout (location = 0) in int index_in; +layout (location = 1) in vec4 color_in; + +uniform float amount; + +out vec2 tex; +out vec4 color; + +void main() { + if (index_in == 0) { + gl_Position = vec4(0, 0, 0, 1.0); + tex = vec2(0.5, 0.5); + color = vec4(0.75, 0.75, 0.75, 1.5); + } else if (index_in == 1) { + gl_Position = vec4(-1, -1, 0, 1.0); + tex = vec2(0, 0); + color = vec4(1, 1, 1, amount); + } else if (index_in == 2) { + gl_Position = vec4(1, -1, 0, 1); + tex = vec2(1, 0); + color = vec4(1, 1, 1, amount); + } else if (index_in == 3) { + gl_Position = vec4(1, 1, 0, 1); + tex = vec2(1, 1); + color = vec4(1, 1, 1, amount); + } else if (index_in == 4) { + gl_Position = vec4(-1, 1, 0, 1); + tex = vec2(0, 1); + color = vec4(1, 1, 1, amount); + } else if (index_in == 5) { + gl_Position = vec4(-1, -1, 0, 1.0); + tex = vec2(0, 0); + color = vec4(1, 1, 1, amount); + } +} diff --git a/goal_src/jak3/engine/gfx/blit-displays.gc b/goal_src/jak3/engine/gfx/blit-displays.gc index f45c893156..df99e8acab 100644 --- a/goal_src/jak3/engine/gfx/blit-displays.gc +++ b/goal_src/jak3/engine/gfx/blit-displays.gc @@ -221,18 +221,23 @@ (set-vector! (-> (the-as (inline-array vector4w) v1-0) 2) 96 96 96 192) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 3) 4088 3320 0 0) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 4) 5120 (* arg2 8) #xffffff #x10000) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 5) 128 128 128 arg3) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 6) 8 8 0 0) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 7) 0 0 #xffffff 0) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 8) 128 128 128 arg3) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 9) 8184 8 0 0) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 10) #x2800 0 #xffffff #x10000) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 11) 128 128 128 arg3) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 12) 8184 (+ (* (+ arg1 -1) 16) 8) 0 0) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 13) #x2800 (* arg2 16) #xffffff #x10000) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 14) 128 128 128 arg3) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 15) 8 (+ (* (+ arg1 -1) 16) 8) 0 0) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 16) 0 (* arg2 16) #xffffff #x10000) + (set-vector! (-> (the-as (inline-array vector4w) v1-0) 17) 128 128 128 arg3) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 18) 8 8 0 0) (set-vector! (-> (the-as (inline-array vector4w) v1-0) 19) 0 0 #xffffff 0) @@ -551,6 +556,19 @@ ) ) +(defun add-pc-slow-time ((dma-buf dma-buffer)) + (dma-buffer-add-cnt-vif2 + dma-buf + 1 + (new 'static 'vif-tag :cmd (vif-cmd pc-port) :imm #x15) + (new 'static 'vif-tag) + ) + (let ((ret (-> dma-buf base))) + (&+! (-> dma-buf base) (* 16 1)) + (the vector ret) + ) + ) + (defmethod draw-brightness-and-contrast ((this blit-displays-work) (arg0 dma-buffer) (arg1 float) (arg2 float)) (set-display-gs-state arg0 408 512 416 0 0) (let ((s4-1 (fmax 0.0 (fmin 1.0 arg2))) @@ -781,10 +799,12 @@ ;; destination is the display buffer (set-display-gs-state s4-5 (-> s0-0 display-fbp) 640 s2-0 (shl #xff00 16) 0) ;; draw either normal or slow-time effect. - ;; currently this slow-time effect is ignored by the BlitDisplays renderer (if (= f30-0 1.0) (blit-standard this s4-5 416 s2-0 128) - (blit-slow-time this s4-5 416 s2-0 (the int (* 128.0 f30-0))) + + ;; og:preserve-this + ;;(blit-slow-time this s4-5 416 s2-0 (the int (* 128.0 f30-0))) + (set! (-> (add-pc-slow-time s4-5) x) f30-0) ) ) )