diff --git a/game/graphics/opengl_renderer/foreground/Merc2.cpp b/game/graphics/opengl_renderer/foreground/Merc2.cpp index dd8bee66e82..24322fc7488 100644 --- a/game/graphics/opengl_renderer/foreground/Merc2.cpp +++ b/game/graphics/opengl_renderer/foreground/Merc2.cpp @@ -547,6 +547,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, bool model_disables_fog = flags->bitflags & 2; bool model_uses_pc_blerc = flags->bitflags & 4 && !is_custom_model; bool model_disables_envmap = flags->bitflags & 8; + bool model_no_texture = flags->bitflags & 16; input_data += 32; float blerc_weights[kMaxBlerc]; @@ -612,13 +613,29 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, u32 first_bone = alloc_bones(bone_count, skel_matrix_buffer); // allocate lights + if (current_lights.w1) { + if (render_state->version != GameVersion::Jak3) { + current_lights.w1 = 0; // force off merc fade in jak2/1 - a bunch of stuff uses this + } + } u32 lights = alloc_lights(current_lights); stats->num_lights++; u64 hash = fnv64(model->name); + DrawArgs args; + args.lev_bucket = lev_bucket; + args.jak1_water_mode = uses_water; + args.disable_fog = model_disables_fog; + args.hash = hash; + args.lights = lights; + args.first_bone = first_bone; + args.no_texture = render_state->version == GameVersion::Jak3 && model_no_texture; + // loop over effects, creating draws for each for (size_t ei = 0; ei < model->effects.size(); ei++) { + args.fade = fade_buffer + 4 * ei; + // game has disabled it? if (!(current_effect_enable_bits & (1ull << ei))) { continue; @@ -630,6 +647,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, } bool ignore_alpha = !!(current_ignore_alpha_bits & (1ull << ei)); + args.ignore_alpha = ignore_alpha; auto& effect = model->effects[ei]; bool should_envmap = effect.has_envmap && !model_disables_envmap; @@ -640,25 +658,20 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, // do fixed draws: for (auto& fdraw : effect.mod.fix_draw) { - alloc_normal_draw(fdraw, ignore_alpha, lev_bucket, first_bone, lights, uses_water, - model_disables_fog, hash); + alloc_normal_draw(fdraw, args); if (should_envmap) { - try_alloc_envmap_draw(fdraw, effect.envmap_mode, effect.envmap_texture, lev_bucket, - fade_buffer + 4 * ei, first_bone, lights, uses_water); + try_alloc_envmap_draw(fdraw, effect.envmap_mode, effect.envmap_texture, args); } } // do mod draws for (auto& mdraw : effect.mod.mod_draw) { - auto n = alloc_normal_draw(mdraw, ignore_alpha, lev_bucket, first_bone, lights, uses_water, - model_disables_fog, hash); + auto n = alloc_normal_draw(mdraw, args); // modify the draw, set the mod flag and point it to the opengl buffer n->flags |= MOD_VTX; n->mod_vtx_buffer = mod_opengl_buffers[ei]; if (should_envmap) { - auto e = - try_alloc_envmap_draw(mdraw, effect.envmap_mode, effect.envmap_texture, lev_bucket, - fade_buffer + 4 * ei, first_bone, lights, uses_water); + auto e = try_alloc_envmap_draw(mdraw, effect.envmap_mode, effect.envmap_texture, args); if (e) { e->flags |= MOD_VTX; e->mod_vtx_buffer = mod_opengl_buffers[ei]; @@ -669,11 +682,9 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, // no mod, just do all_draws for (auto& draw : effect.all_draws) { if (should_envmap) { - try_alloc_envmap_draw(draw, effect.envmap_mode, effect.envmap_texture, lev_bucket, - fade_buffer + 4 * ei, first_bone, lights, uses_water); + try_alloc_envmap_draw(draw, effect.envmap_mode, effect.envmap_texture, args); } - alloc_normal_draw(draw, ignore_alpha, lev_bucket, first_bone, lights, uses_water, - model_disables_fog, hash); + alloc_normal_draw(draw, args); } } } @@ -722,8 +733,8 @@ void Merc2::init_shader_common(Shader& shader, Uniforms* uniforms, bool include_ auto id = shader.id(); shader.activate(); if (include_lights) { - uniforms->light_direction[0] = glGetUniformLocation(id, "light_dir0"); - uniforms->light_direction[1] = glGetUniformLocation(id, "light_dir1"); + uniforms->light_direction[0] = glGetUniformLocation(id, "light_dir0_fade"); + uniforms->light_direction[1] = glGetUniformLocation(id, "light_dir1_fade_en"); uniforms->light_direction[2] = glGetUniformLocation(id, "light_dir2"); uniforms->light_color[0] = glGetUniformLocation(id, "light_col0"); uniforms->light_color[1] = glGetUniformLocation(id, "light_col1"); @@ -1042,14 +1053,10 @@ Merc2::ModBuffers Merc2::alloc_mod_vtx_buffer(const LevelData* lev) { Merc2::Draw* Merc2::try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw, const DrawMode& envmap_mode, u32 envmap_texture, - LevelDrawBucket* lev_bucket, - const u8* fade, - u32 first_bone, - u32 lights, - bool jak1_water_mode) { + const DrawArgs& args) { bool nonzero_fade = false; for (int i = 0; i < 4; i++) { - if (fade[i]) { + if (args.fade[i]) { nonzero_fade = true; break; } @@ -1058,58 +1065,54 @@ Merc2::Draw* Merc2::try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw, return nullptr; } - Draw* draw = &lev_bucket->envmap_draws[lev_bucket->next_free_envmap_draw++]; + Draw* draw = &args.lev_bucket->envmap_draws[args.lev_bucket->next_free_envmap_draw++]; draw->flags = 0; draw->first_index = mdraw.first_index; draw->index_count = mdraw.index_count; draw->mode = envmap_mode; draw->hash = 0; - if (jak1_water_mode) { + if (args.jak1_water_mode) { draw->mode.enable_ab(); draw->mode.disable_depth_write(); } draw->texture = envmap_texture; - draw->first_bone = first_bone; - draw->light_idx = lights; + draw->first_bone = args.first_bone; + draw->light_idx = args.lights; draw->num_triangles = mdraw.num_triangles; for (int i = 0; i < 4; i++) { - draw->fade[i] = fade[i]; + draw->fade[i] = args.fade[i]; } return draw; } -Merc2::Draw* Merc2::alloc_normal_draw(const tfrag3::MercDraw& mdraw, - bool ignore_alpha, - LevelDrawBucket* lev_bucket, - u32 first_bone, - u32 lights, - bool jak1_water_mode, - bool disable_fog, - u64 hash) { - Draw* draw = &lev_bucket->draws[lev_bucket->next_free_draw++]; +Merc2::Draw* Merc2::alloc_normal_draw(const tfrag3::MercDraw& mdraw, const DrawArgs& args) { + Draw* draw = &args.lev_bucket->draws[args.lev_bucket->next_free_draw++]; draw->flags = 0; draw->first_index = mdraw.first_index; draw->index_count = mdraw.index_count; draw->mode = mdraw.mode; - draw->hash = hash; - if (jak1_water_mode) { + draw->hash = args.hash; + if (args.jak1_water_mode) { draw->mode.set_ab(true); draw->mode.disable_depth_write(); } - if (disable_fog) { + if (args.disable_fog) { draw->mode.set_fog(false); // but don't toggle it the other way? } draw->texture = mdraw.eye_id == 0xff ? mdraw.tree_tex_id : (0xefffff00 | mdraw.eye_id); - draw->first_bone = first_bone; - draw->light_idx = lights; + draw->first_bone = args.first_bone; + draw->light_idx = args.lights; draw->num_triangles = mdraw.num_triangles; draw->no_strip = mdraw.no_strip; - if (ignore_alpha) { + if (args.ignore_alpha) { draw->flags |= IGNORE_ALPHA; } + if (args.no_texture) { + draw->flags |= NO_TEXTURE; + } for (int i = 0; i < 4; i++) { draw->fade[i] = 0; } @@ -1281,8 +1284,18 @@ void Merc2::do_draws(const Draw* draw_array, } if ((int)draw.light_idx != last_light && !set_fade) { - set_uniform(uniforms.light_direction[0], m_lights_buffer[draw.light_idx].direction0); - set_uniform(uniforms.light_direction[1], m_lights_buffer[draw.light_idx].direction1); + const auto& l0_dir = m_lights_buffer[draw.light_idx].direction0; + const auto& l1_dir = m_lights_buffer[draw.light_idx].direction1; + float fade = 1.f; + float fade_enable = 0.f; + if (m_lights_buffer[draw.light_idx].w1) { + fade = m_lights_buffer[draw.light_idx].w2 / 128.f; + fade_enable = 1.f; + } + math::Vector4f l0_dir_f(l0_dir.x(), l0_dir.y(), l0_dir.z(), fade); + set_uniform(uniforms.light_direction[0], l0_dir_f); + math::Vector4f l1_dir_f(l1_dir.x(), l1_dir.y(), l1_dir.z(), fade_enable); + set_uniform(uniforms.light_direction[1], l1_dir_f); set_uniform(uniforms.light_direction[2], m_lights_buffer[draw.light_idx].direction2); set_uniform(uniforms.light_color[0], m_lights_buffer[draw.light_idx].color0); set_uniform(uniforms.light_color[1], m_lights_buffer[draw.light_idx].color1); @@ -1290,24 +1303,52 @@ void Merc2::do_draws(const Draw* draw_array, set_uniform(uniforms.light_ambient, m_lights_buffer[draw.light_idx].ambient); last_light = draw.light_idx; } - setup_opengl_from_draw_mode(draw.mode, GL_TEXTURE0, use_mipmaps_for_filtering); glUniform1i(uniforms.decal, draw.mode.get_decal()); + glUniform1i(uniforms.gfx_hack_no_tex, (draw.flags & NO_TEXTURE) != 0); if (set_fade) { math::Vector4f fade = math::Vector4f(draw.fade[0], draw.fade[1], draw.fade[2], draw.fade[3]) / 255.f; set_uniform(uniforms.fade, fade); ASSERT(draw.mode.get_alpha_blend() == DrawMode::AlphaBlend::SRC_0_DST_DST); - // glBindTexture(GL_TEXTURE_2D, render_state->texture_pool->get_placeholder_texture()); } - prof.add_draw_call(); - prof.add_tri(draw.num_triangles); - glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_bones_buffer, - sizeof(math::Vector4f) * draw.first_bone, 128 * sizeof(ShaderMercMat)); - glDrawElements(draw.no_strip ? GL_TRIANGLES : GL_TRIANGLE_STRIP, draw.index_count, - GL_UNSIGNED_INT, (void*)(sizeof(u32) * draw.first_index)); + if (m_lights_buffer[draw.light_idx].w1 && !set_fade) { + DrawMode mode = draw.mode; + mode.set_alpha_blend(DrawMode::AlphaBlend::SRC_DST_SRC_DST); + mode.set_ab(true); + setup_opengl_from_draw_mode(mode, GL_TEXTURE0, use_mipmaps_for_filtering); + + prof.add_draw_call(2); + prof.add_tri(draw.num_triangles * 2); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_bones_buffer, + sizeof(math::Vector4f) * draw.first_bone, 128 * sizeof(ShaderMercMat)); + // draw rgb + const auto& l1_dir = m_lights_buffer[draw.light_idx].direction1; + math::Vector4f l1_dir_f(l1_dir.x(), l1_dir.y(), l1_dir.z(), 1); + set_uniform(uniforms.light_direction[1], l1_dir_f); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + glDrawElements(draw.no_strip ? GL_TRIANGLES : GL_TRIANGLE_STRIP, draw.index_count, + GL_UNSIGNED_INT, (void*)(sizeof(u32) * draw.first_index)); + // draw a + setup_opengl_from_draw_mode(draw.mode, GL_TEXTURE0, use_mipmaps_for_filtering); + math::Vector4f l1_dir_f_off(l1_dir.x(), l1_dir.y(), l1_dir.z(), -1); + set_uniform(uniforms.light_direction[1], l1_dir_f_off); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + glDrawElements(draw.no_strip ? GL_TRIANGLES : GL_TRIANGLE_STRIP, draw.index_count, + GL_UNSIGNED_INT, (void*)(sizeof(u32) * draw.first_index)); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + } else { + setup_opengl_from_draw_mode(draw.mode, GL_TEXTURE0, use_mipmaps_for_filtering); + prof.add_draw_call(); + prof.add_tri(draw.num_triangles); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_bones_buffer, + sizeof(math::Vector4f) * draw.first_bone, 128 * sizeof(ShaderMercMat)); + glDrawElements(draw.no_strip ? GL_TRIANGLES : GL_TRIANGLE_STRIP, draw.index_count, + GL_UNSIGNED_INT, (void*)(sizeof(u32) * draw.first_index)); + } } if (!normal_vtx_buffer_bound) { diff --git a/game/graphics/opengl_renderer/foreground/Merc2.h b/game/graphics/opengl_renderer/foreground/Merc2.h index 9705907b664..b03ccef846e 100644 --- a/game/graphics/opengl_renderer/foreground/Merc2.h +++ b/game/graphics/opengl_renderer/foreground/Merc2.h @@ -69,11 +69,11 @@ class Merc2 { struct VuLights { math::Vector3f direction0; - u32 w0; + u32 w0; // 12 math::Vector3f direction1; - u32 w1; + u32 w1; // 28 math::Vector3f direction2; - u32 w2; + u32 w2; // 44 math::Vector4f color0; math::Vector4f color1; math::Vector4f color2; @@ -177,6 +177,7 @@ class Merc2 { enum DrawFlags { IGNORE_ALPHA = 1, MOD_VTX = 2, + NO_TEXTURE = 4, }; struct Draw { @@ -208,23 +209,25 @@ class Merc2 { next_free_envmap_draw = 0; } }; - Draw* alloc_normal_draw(const tfrag3::MercDraw& mdraw, - bool ignore_alpha, - LevelDrawBucket* lev_bucket, - u32 first_bone, - u32 lights, - bool jak1_water_mode, - bool disable_fog, - u64 hash); + + struct DrawArgs { + LevelDrawBucket* lev_bucket; + const u8* fade; + bool jak1_water_mode; + bool ignore_alpha; + bool disable_fog; + bool no_texture; + u64 hash; + u32 lights; + u32 first_bone; + }; + + Draw* alloc_normal_draw(const tfrag3::MercDraw& mdraw, const DrawArgs& args); Draw* try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw, const DrawMode& envmap_mode, u32 envmap_texture, - LevelDrawBucket* lev_bucket, - const u8* fade, - u32 first_bone, - u32 lights, - bool jak1_water_mode); + const DrawArgs& args); void do_draws(const Draw* draw_array, const LevelData* lev, diff --git a/game/graphics/opengl_renderer/shaders/merc2.frag b/game/graphics/opengl_renderer/shaders/merc2.frag index 962e6486e0d..67a18f5a84f 100644 --- a/game/graphics/opengl_renderer/shaders/merc2.frag +++ b/game/graphics/opengl_renderer/shaders/merc2.frag @@ -5,11 +5,12 @@ in vec4 vtx_color; in vec2 vtx_st; in float fog; - uniform sampler2D tex_T0; uniform vec4 fog_color; uniform int ignore_alpha; +uniform vec4 light_dir0_fade; +uniform vec4 light_dir1_fade_en; uniform int decal_enable; @@ -25,10 +26,20 @@ void main() { color = T0; } color.a *= 2; - //color.a = T0.a * 4; } else { color.rgb = vtx_color.rgb; - color.a = 1; + + if (decal_enable == 0) { + color.a = vtx_color.a * 2; + } else { + color.a = 1; + } + } + + if (light_dir1_fade_en.w > 0) { + color.a = light_dir0_fade.w; + } else if (light_dir1_fade_en.w < 0) { + color.a *= light_dir0_fade.w; } diff --git a/game/graphics/opengl_renderer/shaders/merc2.vert b/game/graphics/opengl_renderer/shaders/merc2.vert index 609803b5cc2..fa591e54364 100644 --- a/game/graphics/opengl_renderer/shaders/merc2.vert +++ b/game/graphics/opengl_renderer/shaders/merc2.vert @@ -9,8 +9,8 @@ layout (location = 4) in vec4 rgba; layout (location = 5) in uvec3 mats; // light control -uniform vec3 light_dir0; -uniform vec3 light_dir1; +uniform vec4 light_dir0_fade; +uniform vec4 light_dir1_fade_en; uniform vec3 light_dir2; uniform vec4 light_col0; uniform vec4 light_col1; @@ -84,7 +84,7 @@ void main() { vec4 transformed = perspective_matrix * vtx_pos; rotated_nrm = normalize(rotated_nrm); - vec3 light_intensity = light_dir0 * rotated_nrm.x + light_dir1 * rotated_nrm.y + light_dir2 * rotated_nrm.z; + vec3 light_intensity = light_dir0_fade.xyz * rotated_nrm.x + light_dir1_fade_en.xyz * rotated_nrm.y + light_dir2 * rotated_nrm.z; light_intensity = max(light_intensity, vec3(0, 0, 0)); vec4 light_color = light_ambient diff --git a/goal_src/jak3/engine/gfx/foreground/foreground.gc b/goal_src/jak3/engine/gfx/foreground/foreground.gc index a5e7dbc702c..eeb698479b6 100644 --- a/goal_src/jak3/engine/gfx/foreground/foreground.gc +++ b/goal_src/jak3/engine/gfx/foreground/foreground.gc @@ -1633,6 +1633,7 @@ (disable-fog 1) (pc-blerc 2) (disable-envmap 3) + (no-textures 4) ) (deftype pc-merc-flags (structure) @@ -1750,6 +1751,9 @@ (when (logtest? (-> dc global-effect) (draw-control-global-effect disable-envmap)) (logior! (-> flags bit-flags) (pc-merc-bits disable-envmap)) ) + (when (logtest? (-> dc global-effect) (draw-control-global-effect no-textures)) + (logior! (-> flags bit-flags) (pc-merc-bits no-textures)) + ) (set! (-> flags enable-mask) enable-mask) (set! (-> flags ignore-alpha-mask) ignore-alpha-mask) )