fix shadow colors in jak 1 and jak 2 shadow crash (#2647)

Fixes Jak 1 shadow color. Old behavior is subtractive blend with a
hardcoded value, which often times look way too dark, but it looks like
the actual game uses some sort of multiplicative blend and a
customizable shadow color (for all shadows at once).

Before vs after:

![image](https://github.com/open-goal/jak-project/assets/7569514/a409a403-9ddf-40dd-a74f-a29bd9b98323)

![20230514234953763_gk_HxercNamqn](https://github.com/open-goal/jak-project/assets/7569514/211565ae-405f-4056-96e5-ec188d2c0a30)


![image](https://github.com/open-goal/jak-project/assets/7569514/f84244a6-153c-4f7d-84d0-dae57147e4ae)

![20230514235005037_gk_jGjwKFhnLE](https://github.com/open-goal/jak-project/assets/7569514/4262d136-3130-4791-ae70-14d4369ba8d4)


Also fixes #2646
This commit is contained in:
ManDude
2023-05-15 01:01:49 +01:00
committed by GitHub
parent 08b9a631dc
commit ecf590f30e
6 changed files with 40 additions and 27 deletions
@@ -242,15 +242,15 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
BucketId::TEX_ALL_MAP);
// 320
init_bucket_renderer<ProgressRenderer>("progress", BucketCategory::OTHER, BucketId::PROGRESS,
0x8000);
0x1000);
init_bucket_renderer<DirectRenderer>("screen-filter", BucketCategory::OTHER,
BucketId::SCREEN_FILTER, 256);
init_bucket_renderer<DirectRenderer>("subtitle", BucketCategory::OTHER, BucketId::SUBTITLE,
0x8000);
0x1000);
init_bucket_renderer<DirectRenderer>("debug2", BucketCategory::OTHER, BucketId::DEBUG2, 0x8000);
init_bucket_renderer<DirectRenderer>("debug-no-zbuf2", BucketCategory::OTHER,
BucketId::DEBUG_NO_ZBUF2, 0x8000);
init_bucket_renderer<DirectRenderer>("debug3", BucketCategory::OTHER, BucketId::DEBUG3, 0x1000);
init_bucket_renderer<DirectRenderer>("debug3", BucketCategory::OTHER, BucketId::DEBUG3, 0x2000);
auto eye_renderer = std::make_unique<EyeRenderer>("eyes", 0);
m_render_state.eye_renderer = eye_renderer.get();
@@ -259,7 +259,7 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
// for now, for any unset renderers, just set them to an EmptyBucketRenderer.
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
if (!m_bucket_renderers[i]) {
init_bucket_renderer<EmptyBucketRenderer>(fmt::format("bucket{}", i), BucketCategory::OTHER,
init_bucket_renderer<EmptyBucketRenderer>(fmt::format("bucket-{}", i), BucketCategory::OTHER,
i);
}
@@ -353,6 +353,8 @@ void OpenGLRenderer::init_bucket_renderers_jak1() {
// 22 : SHRUB_BILLBOARD_LEVEL0
// 23 : SHRUB_TRANS_LEVEL0
// 24 : SHRUB_GENERIC_LEVEL0
init_bucket_renderer<Generic2>("l0-shrub-generic", BucketCategory::GENERIC,
BucketId::SHRUB_GENERIC_LEVEL0);
//-----------------------
// LEVEL 1 shrub texture
@@ -366,7 +368,7 @@ void OpenGLRenderer::init_bucket_renderers_jak1() {
// 28 : SHRUB_BILLBOARD_LEVEL1
// 29 : SHRUB_TRANS_LEVEL1
// 30 : SHRUB_GENERIC_LEVEL1
init_bucket_renderer<Generic2>("mystery-generic", BucketCategory::GENERIC,
init_bucket_renderer<Generic2>("l1-shrub-generic", BucketCategory::GENERIC,
BucketId::SHRUB_GENERIC_LEVEL1);
//-----------------------
@@ -484,7 +486,7 @@ void OpenGLRenderer::init_bucket_renderers_jak1() {
// for now, for any unset renderers, just set them to an EmptyBucketRenderer.
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
if (!m_bucket_renderers[i]) {
init_bucket_renderer<EmptyBucketRenderer>(fmt::format("bucket{}", i), BucketCategory::OTHER,
init_bucket_renderer<EmptyBucketRenderer>(fmt::format("bucket-{}", i), BucketCategory::OTHER,
(BucketId)i);
}
@@ -110,7 +110,7 @@ void ShadowRenderer::xgkick(u16 imm) {
for (int i = 0; i < 4; i++) {
rgba[i] = data[offset + i * 4];
}
// fmt::print("rgbap: {} {} {} {}\n", rgba[0], rgba[1], rgba[2], rgba[3]);
// fmt::print("rgbaq: {} {} {} {}\n", rgba[0], rgba[1], rgba[2], rgba[3]);
break;
case GifTag::RegisterDescriptor::XYZF2:
// handle_xyzf2_packed(data + offset, render_state, prof);
@@ -302,10 +302,20 @@ void ShadowRenderer::render(DmaFollower& dma,
run_mscal_vu2c(mscal.immediate);
} else if (next.vifcode0().kind == VifCode::Kind::FLUSHA &&
next.vifcode1().kind == VifCode::Kind::DIRECT) {
// there's 4 direct transfers to set up various registers.
// we only care about the one that has the color value.
auto xfer1 = dma.read_and_advance();
dma.read_and_advance();
dma.read_and_advance();
dma.read_and_advance();
auto r = *(xfer1.data + 24);
auto g = *(xfer1.data + 25);
auto b = *(xfer1.data + 26);
auto a = *(xfer1.data + 27);
m_color.x() = r / 255.0f;
m_color.y() = g / 255.0f;
m_color.z() = b / 255.0f;
m_color.w() = a / 128.0f;
fmt::print("rgba: {} {} {} {}\n", r, g, b, a);
} else {
ASSERT_MSG(false, fmt::format("{} {}", next.vifcode0().print(), next.vifcode1().print()));
}
@@ -349,7 +359,6 @@ void ShadowRenderer::draw(SharedRenderState* render_state, ScopedProfilerNode& p
glDepthMask(GL_FALSE); // no depth writes.
if (m_debug_draw_volume) {
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
} else {
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color writes.
@@ -361,7 +370,7 @@ void ShadowRenderer::draw(SharedRenderState* render_state, ScopedProfilerNode& p
{
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::SHADOW].id(), "color_uniform"),
0., 0.4, 0., 0.5);
0.0f, 128.0f / 256, 0.0f, 127.0f / 256);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_front_index * sizeof(u32), m_front_indices,
GL_STREAM_DRAW);
@@ -372,8 +381,8 @@ void ShadowRenderer::draw(SharedRenderState* render_state, ScopedProfilerNode& p
if (m_debug_draw_volume) {
glDisable(GL_BLEND);
glUniform4f(
glGetUniformLocation(render_state->shaders[ShaderId::SHADOW].id(), "color_uniform"), 0.,
0.0, 0., 0.5);
glGetUniformLocation(render_state->shaders[ShaderId::SHADOW].id(), "color_uniform"), 0.0f,
0.0f, 0.0f, 0.5f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawElements(GL_TRIANGLES, (m_next_front_index - 6), GL_UNSIGNED_INT, nullptr);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
@@ -385,7 +394,7 @@ void ShadowRenderer::draw(SharedRenderState* render_state, ScopedProfilerNode& p
{
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::SHADOW].id(), "color_uniform"),
0.4, 0.0, 0., 0.5);
128.0f / 256, 0.0f, 0.0f, 130.0f / 256);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_back_index * sizeof(u32), m_back_indices,
GL_STREAM_DRAW);
@@ -397,8 +406,8 @@ void ShadowRenderer::draw(SharedRenderState* render_state, ScopedProfilerNode& p
if (m_debug_draw_volume) {
glDisable(GL_BLEND);
glUniform4f(
glGetUniformLocation(render_state->shaders[ShaderId::SHADOW].id(), "color_uniform"), 0.,
0.0, 0., 0.5);
glGetUniformLocation(render_state->shaders[ShaderId::SHADOW].id(), "color_uniform"), 0.0f,
0.0f, 0.0f, 0.5f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawElements(GL_TRIANGLES, (m_next_back_index - 0), GL_UNSIGNED_INT, nullptr);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
@@ -412,20 +421,20 @@ void ShadowRenderer::draw(SharedRenderState* render_state, ScopedProfilerNode& p
// finally, draw shadow.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer[0]);
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::SHADOW].id(), "color_uniform"),
0.13, 0.13, 0.13, 0.5);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
m_color.x(), m_color.y(), m_color.z(), m_color.w());
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
// glStencilFunc(GL_GREATER, 0, 0);
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDepthFunc(GL_ALWAYS);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ONE, GL_ZERO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(sizeof(u32) * (m_next_front_index - 6)));
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
prof.add_draw_call();
prof.add_tri(2);
glBlendEquation(GL_FUNC_ADD);
glDepthMask(GL_TRUE);
glDisable(GL_STENCIL_TEST);
@@ -119,6 +119,8 @@ class ShadowRenderer : public BucketRenderer {
u32 m_next_front_index = 0;
u32 m_next_back_index = 0;
math::Vector4f m_color;
struct {
// index is front, back
GLuint vertex_buffer, index_buffer[2], vao;
@@ -63,7 +63,6 @@ void Shadow2::reset_buffers() {
}
void Shadow2::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) {
reset_buffers();
// jump to bucket
dma.read_and_advance();
@@ -79,6 +78,8 @@ void Shadow2::render(DmaFollower& dma, SharedRenderState* render_state, ScopedPr
return;
}
reset_buffers();
// shadow-vu1-constants
ASSERT(maybe_constants.size_bytes >= sizeof(ShadowVu1Constants));
FrameConstants frame_constants;
@@ -550,7 +551,6 @@ void Shadow2::draw_buffers(SharedRenderState* render_state,
if (have_darken) {
glColorMask(darken_channel[0], darken_channel[1], darken_channel[2], false);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glUniform4f(m_ogl.uniforms.color, (128 - m_color[0]) / 256.f, (128 - m_color[1]) / 256.f,
(128 - m_color[2]) / 256.f, 0);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
@@ -575,4 +575,4 @@ void Shadow2::draw_buffers(SharedRenderState* render_state,
glDepthMask(GL_TRUE);
glDisable(GL_STENCIL_TEST);
}
}
@@ -6,8 +6,8 @@
class Shadow2 : public BucketRenderer {
public:
static constexpr int kMaxVerts = 8192 * 3;
static constexpr int kMaxInds = 8192 * 3;
static constexpr int kMaxVerts = 8192 * 3 * 2;
static constexpr int kMaxInds = kMaxVerts;
Shadow2(const std::string& name, int my_id);
~Shadow2();
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
@@ -4,5 +4,5 @@ out vec4 color;
uniform vec4 color_uniform;
void main() {
color = color_uniform;
color = color_uniform * 2;
}