Skip to content

Commit

Permalink
[jak3] Add merc fade and support for no texture flag (#3710)
Browse files Browse the repository at this point in the history
  • Loading branch information
water111 and water111 authored Oct 5, 2024
1 parent 452f132 commit 10008ca
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 73 deletions.
143 changes: 92 additions & 51 deletions game/graphics/opengl_renderer/foreground/Merc2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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];
Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -1281,33 +1284,71 @@ 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);
set_uniform(uniforms.light_color[2], m_lights_buffer[draw.light_idx].color2);
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) {
Expand Down
35 changes: 19 additions & 16 deletions game/graphics/opengl_renderer/foreground/Merc2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -177,6 +177,7 @@ class Merc2 {
enum DrawFlags {
IGNORE_ALPHA = 1,
MOD_VTX = 2,
NO_TEXTURE = 4,
};

struct Draw {
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 14 additions & 3 deletions game/graphics/opengl_renderer/shaders/merc2.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}


Expand Down
6 changes: 3 additions & 3 deletions game/graphics/opengl_renderer/shaders/merc2.vert
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 10008ca

Please sign in to comment.