diff --git a/common/dma/gs.h b/common/dma/gs.h index c02698dbdc..73c3805328 100644 --- a/common/dma/gs.h +++ b/common/dma/gs.h @@ -362,8 +362,9 @@ class DrawMode { DISABLED = 0, SRC_DST_SRC_DST = 1, SRC_0_SRC_DST = 2, - SRC_0_FIX_DST = 3, // fix = 128 - SRC_DST_FIX_DST = 4 // fix = 64 + SRC_0_FIX_DST = 3, // fix = 128 + SRC_DST_FIX_DST = 4, // fix = 64 + ZERO_SRC_SRC_DST = 5, }; enum class AlphaTest { diff --git a/game/graphics/opengl_renderer/BucketRenderer.cpp b/game/graphics/opengl_renderer/BucketRenderer.cpp index 25d333d328..810db8a91a 100644 --- a/game/graphics/opengl_renderer/BucketRenderer.cpp +++ b/game/graphics/opengl_renderer/BucketRenderer.cpp @@ -71,7 +71,9 @@ RenderMux::RenderMux(const std::string& name, : BucketRenderer(name, my_id), m_renderers(std::move(renderers)) { for (auto& r : m_renderers) { m_name_strs.push_back(r->name_and_id()); - m_name_str_ptrs.push_back(m_name_strs.back().data()); + } + for (auto& n : m_name_strs) { + m_name_str_ptrs.push_back(n.data()); } } diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.cpp b/game/graphics/opengl_renderer/OpenGLRenderer.cpp index 5734d1f721..35e8929e6b 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.cpp +++ b/game/graphics/opengl_renderer/OpenGLRenderer.cpp @@ -196,8 +196,9 @@ void OpenGLRenderer::init_bucket_renderers() { init_bucket_renderer("pre-sprite-tex", BucketId::PRE_SPRITE_TEX); // 65 std::vector> sprite_renderers; - sprite_renderers.push_back(std::make_unique("sprite-renderer", BucketId::SPRITE)); + // the first renderer added will be the default for sprite. sprite_renderers.push_back(std::make_unique("sprite-3", BucketId::SPRITE)); + sprite_renderers.push_back(std::make_unique("sprite-renderer", BucketId::SPRITE)); init_bucket_renderer("sprite", BucketId::SPRITE, std::move(sprite_renderers)); // 66 init_bucket_renderer("debug-draw-0", BucketId::DEBUG_DRAW_0, 0x20000, diff --git a/game/graphics/opengl_renderer/Sprite3.cpp b/game/graphics/opengl_renderer/Sprite3.cpp index 88d82f1e3a..fe4ec66365 100644 --- a/game/graphics/opengl_renderer/Sprite3.cpp +++ b/game/graphics/opengl_renderer/Sprite3.cpp @@ -453,11 +453,10 @@ void Sprite3::flush_sprites(SharedRenderState* render_state, // two passes through the buckets. first to build the index buffer u32 idx_offset = 0; - for (auto& kv : m_sprite_buckets) { - memcpy(&m_index_buffer_data[idx_offset], kv.second.ids.data(), - kv.second.ids.size() * sizeof(u32)); - kv.second.offset_in_idx_buffer = idx_offset; - idx_offset += kv.second.ids.size(); + for (const auto bucket : m_bucket_list) { + memcpy(&m_index_buffer_data[idx_offset], bucket->ids.data(), bucket->ids.size() * sizeof(u32)); + bucket->offset_in_idx_buffer = idx_offset; + idx_offset += bucket->ids.size(); } // now upload it @@ -466,10 +465,10 @@ void Sprite3::flush_sprites(SharedRenderState* render_state, GL_STREAM_DRAW); // now do draws! - for (auto& kv : m_sprite_buckets) { - u32 tbp = kv.first >> 32; + for (const auto bucket : m_bucket_list) { + u32 tbp = bucket->key >> 32; DrawMode mode; - mode.as_int() = kv.first & 0xffffffff; + mode.as_int() = bucket->key & 0xffffffff; TextureRecord* tex = nullptr; tex = render_state->texture_pool->lookup(tbp); @@ -497,10 +496,10 @@ void Sprite3::flush_sprites(SharedRenderState* render_state, glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::SPRITE3].id(), "tex_T0"), 0); prof.add_draw_call(); - prof.add_tri(2 * (kv.second.ids.size() / 5)); + prof.add_tri(2 * (bucket->ids.size() / 5)); - glDrawElements(GL_TRIANGLE_STRIP, kv.second.ids.size(), GL_UNSIGNED_INT, - (void*)(kv.second.offset_in_idx_buffer * sizeof(u32))); + glDrawElements(GL_TRIANGLE_STRIP, bucket->ids.size(), GL_UNSIGNED_INT, + (void*)(bucket->offset_in_idx_buffer * sizeof(u32))); if (double_draw) { switch (settings.kind) { @@ -508,7 +507,7 @@ void Sprite3::flush_sprites(SharedRenderState* render_state, break; case DoubleDrawKind::AFAIL_NO_DEPTH_WRITE: prof.add_draw_call(); - prof.add_tri(2 * (kv.second.ids.size() / 5)); + prof.add_tri(2 * (bucket->ids.size() / 5)); glUniform1f( glGetUniformLocation(render_state->shaders[ShaderId::SPRITE3].id(), "alpha_min"), -10.f); @@ -516,8 +515,8 @@ void Sprite3::flush_sprites(SharedRenderState* render_state, glGetUniformLocation(render_state->shaders[ShaderId::SPRITE3].id(), "alpha_max"), settings.aref_second); glDepthMask(GL_FALSE); - glDrawElements(GL_TRIANGLE_STRIP, kv.second.ids.size(), GL_UNSIGNED_INT, - (void*)(kv.second.offset_in_idx_buffer * sizeof(u32))); + glDrawElements(GL_TRIANGLE_STRIP, bucket->ids.size(), GL_UNSIGNED_INT, + (void*)(bucket->offset_in_idx_buffer * sizeof(u32))); break; default: ASSERT(false); @@ -526,6 +525,7 @@ void Sprite3::flush_sprites(SharedRenderState* render_state, } m_sprite_buckets.clear(); + m_bucket_list.clear(); m_last_bucket_key = UINT64_MAX; m_last_bucket = nullptr; m_sprite_idx = 0; @@ -616,6 +616,14 @@ void update_mode_from_alpha1(u64 val, DrawMode& mode) { // Cv = (Cs - Cd) * FIX + Cd ASSERT(reg.fix() == 64); mode.set_alpha_blend(DrawMode::AlphaBlend::SRC_DST_FIX_DST); + } else if (reg.a_mode() == GsAlpha::BlendMode::ZERO_OR_FIXED && + reg.b_mode() == GsAlpha::BlendMode::SOURCE && + reg.c_mode() == GsAlpha::BlendMode::SOURCE && + reg.d_mode() == GsAlpha::BlendMode::DEST) { + // (0 - Cs) * As + Cd + // Cd - Cs * As + // s, d + mode.set_alpha_blend(DrawMode::AlphaBlend::ZERO_SRC_SRC_DST); } else { @@ -667,7 +675,14 @@ void Sprite3::do_block_common(SpriteMode mode, if (key == m_last_bucket_key) { bucket = m_last_bucket; } else { - bucket = &m_sprite_buckets[key]; + auto it = m_sprite_buckets.find(key); + if (it == m_sprite_buckets.end()) { + bucket = &m_sprite_buckets[key]; + bucket->key = key; + m_bucket_list.push_back(bucket); + } else { + bucket = &it->second; + } } u32 start_vtx_id = m_sprite_idx * 4; bucket->ids.push_back(start_vtx_id); diff --git a/game/graphics/opengl_renderer/Sprite3.h b/game/graphics/opengl_renderer/Sprite3.h index 5cdf20c09d..5f52de7998 100644 --- a/game/graphics/opengl_renderer/Sprite3.h +++ b/game/graphics/opengl_renderer/Sprite3.h @@ -90,9 +90,11 @@ class Sprite3 : public BucketRenderer { struct Bucket { std::vector ids; u32 offset_in_idx_buffer = 0; + u64 key = -1; }; std::map m_sprite_buckets; + std::vector m_bucket_list; u64 m_last_bucket_key = UINT64_MAX; Bucket* m_last_bucket = nullptr; diff --git a/game/graphics/opengl_renderer/shaders/sprite3_3d.frag b/game/graphics/opengl_renderer/shaders/sprite3_3d.frag index 2cc5a42546..c22fa3a44e 100644 --- a/game/graphics/opengl_renderer/shaders/sprite3_3d.frag +++ b/game/graphics/opengl_renderer/shaders/sprite3_3d.frag @@ -17,8 +17,6 @@ void main() { } color = fragment_color * T0 * 2.0; - - if (color.a < alpha_min) { discard; } @@ -27,24 +25,3 @@ void main() { discard; } } - -//out vec4 color; -// -//in flat vec4 fragment_color; -//in vec3 tex_coord; -//in flat uvec2 tex_info; -// -//uniform sampler2D tex_T0; -// -// -//void main() { -// vec4 T0 = texture(tex_T0, tex_coord.xy); -// if (tex_info.y == 0) { -// T0.w = 1.0; -// } -// vec4 tex_color = fragment_color * T0 * 2.0; -// if (tex_color.a < 0.016) { -// discard; -// } -// color = tex_color; -//} diff --git a/game/graphics/opengl_renderer/shaders/sprite3_3d.vert b/game/graphics/opengl_renderer/shaders/sprite3_3d.vert index 0e245cc72b..b99ac9d1da 100644 --- a/game/graphics/opengl_renderer/shaders/sprite3_3d.vert +++ b/game/graphics/opengl_renderer/shaders/sprite3_3d.vert @@ -128,12 +128,12 @@ void main() { transformed = offset_pos_vf10 + vf12_rotated * xy0_vf19.x + vf13_rotated_trans * xy0_vf19.y; } else if (rendermode == 2) { // hud sprites - transformed_pos_vf02.xyz *= Q; vec4 offset_pos_vf10 = transformed_pos_vf02 + (matrix == 0 ? hud_hvdf_offset : hud_hvdf_user[matrix - 1]); - scales_vf01.z = min(max(scales_vf01.z, min_scale), max_scale); - scales_vf01.w = min(max(scales_vf01.w, min_scale), max_scale); + // NOTE: no max scale for hud + scales_vf01.z = max(scales_vf01.z, min_scale); + scales_vf01.w = max(scales_vf01.w, min_scale); quat.z *= deg_to_rad; float sp_sin = sin(quat.z); diff --git a/game/graphics/opengl_renderer/tfrag/tfrag_common.cpp b/game/graphics/opengl_renderer/tfrag/tfrag_common.cpp index 7e21058423..067b4cec8b 100644 --- a/game/graphics/opengl_renderer/tfrag/tfrag_common.cpp +++ b/game/graphics/opengl_renderer/tfrag/tfrag_common.cpp @@ -36,21 +36,29 @@ DoubleDraw setup_opengl_from_draw_mode(DrawMode mode, u32 tex_unit, bool mipmap) glEnable(GL_BLEND); switch (mode.get_alpha_blend()) { case DrawMode::AlphaBlend::SRC_DST_SRC_DST: + glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; case DrawMode::AlphaBlend::SRC_0_SRC_DST: + glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; case DrawMode::AlphaBlend::SRC_0_FIX_DST: + glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE, GL_ONE); break; case DrawMode::AlphaBlend::SRC_DST_FIX_DST: // Cv = (Cs - Cd) * FIX + Cd // Cs * FIX * 0.5 // Cd * FIX * 0.5 + glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_CONSTANT_COLOR, GL_CONSTANT_COLOR); glBlendColor(0.5, 0.5, 0.5, 0.5); break; + case DrawMode::AlphaBlend::ZERO_SRC_SRC_DST: + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + break; default: ASSERT(false); }