From d75f0613505f99c7085f2a9bddfbfe0b1b56063c Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Thu, 4 Apr 2024 02:27:42 -0600 Subject: [PATCH 01/10] Implemented dither noise (cherry picked from commit 7321c1a54903d676b02e0a8bcddd48a78935d40e) --- src/graphic/Fast3D/gfx_opengl.cpp | 28 ++++++++++++++++++++++++---- src/graphic/Fast3D/gfx_pc.cpp | 17 +++++++++++------ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/graphic/Fast3D/gfx_opengl.cpp b/src/graphic/Fast3D/gfx_opengl.cpp index f4cf0e89a..5535ac43f 100644 --- a/src/graphic/Fast3D/gfx_opengl.cpp +++ b/src/graphic/Fast3D/gfx_opengl.cpp @@ -418,6 +418,22 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad append_line(fs_buf, &fs_len, "uniform int frame_count;"); append_line(fs_buf, &fs_len, "uniform float noise_scale;"); + append_line(fs_buf, &fs_len, "vec3 colorDither(float _noise_val, vec3 _color)"); + append_line(fs_buf, &fs_len, "{"); + append_line(fs_buf, &fs_len, " vec3 _noise = vec3(_noise_val, _noise_val, _noise_val);"); + append_line(fs_buf, &fs_len, " vec3 threshold = 7.0 / 255.0 * (_noise - 0.5);"); + append_line(fs_buf, &fs_len, " _color = clamp(_color + threshold, 0.0, 1.0);"); + append_line(fs_buf, &fs_len, " _color.rgb = round(_color.rgb * 32.0) / 32.0;"); + append_line(fs_buf, &fs_len, " return _color;"); + append_line(fs_buf, &fs_len, "}"); + append_line(fs_buf, &fs_len, "float alphaDither(float _noise, float _alpha)"); + append_line(fs_buf, &fs_len, "{"); + append_line(fs_buf, &fs_len, " float threshold = 7.0 / 255.0 * (_noise - 0.5);"); + append_line(fs_buf, &fs_len, " _alpha = clamp(_alpha + threshold, 0.0, 1.0);"); + append_line(fs_buf, &fs_len, " _alpha = round(_alpha * 32.0) / 32.0;"); + append_line(fs_buf, &fs_len, " return _alpha;"); + append_line(fs_buf, &fs_len, "}"); + append_line(fs_buf, &fs_len, "float random(in vec3 value) {"); append_line(fs_buf, &fs_len, " float random = dot(sin(value), vec3(12.9898, 78.233, 37.719));"); append_line(fs_buf, &fs_len, " return fract(sin(random) * 143758.5453);"); @@ -554,9 +570,9 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad } if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(fs_buf, &fs_len, - "texel.a *= floor(clamp(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))) + " - "texel.a, 0.0, 1.0));"); + append_line(fs_buf, &fs_len, "texel.a = alphaDither(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))), texel.a);"); + } else if (cc_features.opt_noise) { + append_line(fs_buf, &fs_len, "texel.rgb = colorDither(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))), texel.rgb);"); } if (cc_features.opt_grayscale) { @@ -566,8 +582,12 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad } if (cc_features.opt_alpha) { + append_line(fs_buf, &fs_len, "float cvg = 1.0;"); + append_line(fs_buf, &fs_len, "float alphaValue = texel.a;"); + if (cc_features.opt_alpha_threshold) { - append_line(fs_buf, &fs_len, "if (texel.a < 8.0 / 256.0) discard;"); + append_line(fs_buf, &fs_len, "alphaValue = clamp(alphaValue, 0.0, 1.0);"); + append_line(fs_buf, &fs_len, "if (alphaValue < alphaTestValue) discard;"); } if (cc_features.opt_invisible) { append_line(fs_buf, &fs_len, "texel.a = 0.0;"); diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index cae6ccf15..e2924c753 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -1412,7 +1412,10 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo (g_rdp.other_mode_l & (3 << 16)) == (G_BL_1MA << 16); bool use_fog = (g_rdp.other_mode_l >> 30) == G_BL_CLR_FOG; bool texture_edge = (g_rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA; - bool use_noise = (g_rdp.other_mode_l & (3U << G_MDSFT_ALPHACOMPARE)) == G_AC_DITHER; + bool use_noise = ((g_rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) < G_CYC_COPY) && + ((g_rdp.other_mode_l & (3U << G_MDSFT_ALPHACOMPARE)) == G_AC_DITHER || + (g_rdp.other_mode_h & (3U << G_MDSFT_ALPHADITHER)) == G_AD_NOISE || + (g_rdp.other_mode_h & (3U << G_MDSFT_COLORDITHER)) == G_CD_NOISE); bool use_2cyc = (g_rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_2CYCLE; bool alpha_threshold = (g_rdp.other_mode_l & (3U << G_MDSFT_ALPHACOMPARE)) == G_AC_THRESHOLD; bool invisible = @@ -3283,11 +3286,14 @@ bool gfx_set_fb_handler_custom(Gfx** cmd0) { return false; } +float gfx_calculate_noise_scale() { + return ((float)gfx_current_dimensions.height / SCREEN_HEIGHT) * 0.5f; +} + bool gfx_reset_fb_handler_custom(Gfx** cmd0) { gfx_flush(); fbActive = 0; - gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, - (float)gfx_current_dimensions.height / gfx_native_dimensions.height); + gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, gfx_calculate_noise_scale()); return false; } @@ -3885,8 +3891,7 @@ void gfx_run(Gfx* commands, const std::unordered_map& mtx_replacemen gfx_current_window_dimensions.height, 1, false, true, true, !game_renders_to_framebuffer); gfx_rapi->start_frame(); - gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, - (float)gfx_current_dimensions.height / gfx_native_dimensions.height); + gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, gfx_calculate_noise_scale()); gfx_rapi->clear_framebuffer(); g_rdp.viewport_or_scissor_changed = true; rendering_state.viewport = {}; @@ -4015,7 +4020,7 @@ void gfx_copy_framebuffer(int fb_dst_id, int fb_src_id, bool copyOnce, bool* has } void gfx_reset_framebuffer() { - gfx_rapi->start_draw_to_framebuffer(0, (float)gfx_current_dimensions.height / gfx_native_dimensions.height); + gfx_rapi->start_draw_to_framebuffer(0, gfx_calculate_noise_scale()); gfx_rapi->clear_framebuffer(); } From 49ac5a2b4780298bd4fd8ae4dbae40f731da331d Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Sat, 6 Apr 2024 19:16:43 -0600 Subject: [PATCH 02/10] Implemented noise on directx (cherry picked from commit e344ac3210b12a419d5ae3b62cf7ac66297801fb) --- src/graphic/Fast3D/gfx_direct3d_common.cpp | 25 +++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/graphic/Fast3D/gfx_direct3d_common.cpp b/src/graphic/Fast3D/gfx_direct3d_common.cpp index 003b44c27..360d7af37 100644 --- a/src/graphic/Fast3D/gfx_direct3d_common.cpp +++ b/src/graphic/Fast3D/gfx_direct3d_common.cpp @@ -196,6 +196,23 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f append_line(buf, &len, " float noise_scale;"); append_line(buf, &len, "}"); + append_line(buf, &len, "float3 colorDither(in float _noise_val, in float3 _color)"); + append_line(buf, &len, "{"); + append_line(buf, &len, " float3 _noise = float3(_noise_val, _noise_val, _noise_val);"); + append_line(buf, &len, " float3 threshold = 7.0 / 255.0 * (_noise - 0.5);"); + append_line(buf, &len, " _color = clamp(_color + threshold, 0.0, 1.0);"); + append_line(buf, &len, " _color.rgb = round(_color.rgb * 32.0) / 32.0;"); + append_line(buf, &len, " return _color;"); + append_line(buf, &len, "}"); + + append_line(buf, &len, "float alphaDither(in float _noise, in float _alpha)"); + append_line(buf, &len, "{"); + append_line(buf, &len, " float threshold = 7.0 / 255.0 * (_noise - 0.5);"); + append_line(buf, &len, " _alpha = clamp(_alpha + threshold, 0.0, 1.0);"); + append_line(buf, &len, " _alpha = round(_alpha * 32.0) / 32.0;"); + append_line(buf, &len, " return _alpha;"); + append_line(buf, &len, "}"); + append_line(buf, &len, "float random(in float3 value) {"); append_line(buf, &len, " float random = dot(value, float3(12.9898, 78.233, 37.719));"); append_line(buf, &len, " return frac(sin(random) * 143758.5453);"); @@ -428,14 +445,16 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f } if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(buf, &len, " float2 coords = screenSpace.xy * noise_scale;"); append_line(buf, &len, - " texel.a *= round(saturate(random(float3(floor(coords), noise_frame)) + texel.a - 0.5));"); + " texel.a = alphaDither(random(float3(floor(screenSpace.xy * noise_scale), float(noise_frame))), texel.a);"); } if (cc_features.opt_alpha) { + append_line(buf, &len, " float alphaValue = texel.a;"); + if (cc_features.opt_alpha_threshold) { - append_line(buf, &len, " if (texel.a < 8.0 / 256.0) discard;"); + append_line(buf, &len, "alphaValue = clamp(alphaValue, 0.0, 1.0);"); + append_line(buf, &len, "if (alphaValue < alphaTestValue) discard;"); } if (cc_features.opt_invisible) { append_line(buf, &len, " texel.a = 0.0;"); From 0fc9befaa93fbca27069a503e8022118f56b0669 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Fri, 19 Apr 2024 03:42:50 -0600 Subject: [PATCH 03/10] Fixed tidy --- src/graphic/Fast3D/gfx_direct3d_common.cpp | 3 ++- src/graphic/Fast3D/gfx_opengl.cpp | 8 ++++++-- src/graphic/Fast3D/gfx_pc.cpp | 12 +++++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/graphic/Fast3D/gfx_direct3d_common.cpp b/src/graphic/Fast3D/gfx_direct3d_common.cpp index 360d7af37..211e65709 100644 --- a/src/graphic/Fast3D/gfx_direct3d_common.cpp +++ b/src/graphic/Fast3D/gfx_direct3d_common.cpp @@ -446,7 +446,8 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f if (cc_features.opt_alpha && cc_features.opt_noise) { append_line(buf, &len, - " texel.a = alphaDither(random(float3(floor(screenSpace.xy * noise_scale), float(noise_frame))), texel.a);"); + " texel.a = alphaDither(random(float3(floor(screenSpace.xy * noise_scale), " + "float(noise_frame))), texel.a);"); } if (cc_features.opt_alpha) { diff --git a/src/graphic/Fast3D/gfx_opengl.cpp b/src/graphic/Fast3D/gfx_opengl.cpp index 5535ac43f..ba1c1cd9f 100644 --- a/src/graphic/Fast3D/gfx_opengl.cpp +++ b/src/graphic/Fast3D/gfx_opengl.cpp @@ -570,9 +570,13 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad } if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(fs_buf, &fs_len, "texel.a = alphaDither(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))), texel.a);"); + append_line( + fs_buf, &fs_len, + "texel.a = alphaDither(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))), texel.a);"); } else if (cc_features.opt_noise) { - append_line(fs_buf, &fs_len, "texel.rgb = colorDither(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))), texel.rgb);"); + append_line(fs_buf, &fs_len, + "texel.rgb = colorDither(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))), " + "texel.rgb);"); } if (cc_features.opt_grayscale) { diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index e2924c753..8acd50b63 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -1413,9 +1413,9 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo bool use_fog = (g_rdp.other_mode_l >> 30) == G_BL_CLR_FOG; bool texture_edge = (g_rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA; bool use_noise = ((g_rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) < G_CYC_COPY) && - ((g_rdp.other_mode_l & (3U << G_MDSFT_ALPHACOMPARE)) == G_AC_DITHER || - (g_rdp.other_mode_h & (3U << G_MDSFT_ALPHADITHER)) == G_AD_NOISE || - (g_rdp.other_mode_h & (3U << G_MDSFT_COLORDITHER)) == G_CD_NOISE); + ((g_rdp.other_mode_l & (3U << G_MDSFT_ALPHACOMPARE)) == G_AC_DITHER || + (g_rdp.other_mode_h & (3U << G_MDSFT_ALPHADITHER)) == G_AD_NOISE || + (g_rdp.other_mode_h & (3U << G_MDSFT_COLORDITHER)) == G_CD_NOISE); bool use_2cyc = (g_rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_2CYCLE; bool alpha_threshold = (g_rdp.other_mode_l & (3U << G_MDSFT_ALPHACOMPARE)) == G_AC_THRESHOLD; bool invisible = @@ -3293,7 +3293,8 @@ float gfx_calculate_noise_scale() { bool gfx_reset_fb_handler_custom(Gfx** cmd0) { gfx_flush(); fbActive = 0; - gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, gfx_calculate_noise_scale()); + gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, + gfx_calculate_noise_scale()); return false; } @@ -3891,7 +3892,8 @@ void gfx_run(Gfx* commands, const std::unordered_map& mtx_replacemen gfx_current_window_dimensions.height, 1, false, true, true, !game_renders_to_framebuffer); gfx_rapi->start_frame(); - gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, gfx_calculate_noise_scale()); + gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, + gfx_calculate_noise_scale()); gfx_rapi->clear_framebuffer(); g_rdp.viewport_or_scissor_changed = true; rendering_state.viewport = {}; From bbe1431c6fe31d8868a0a5a587f11bd2685d9bd0 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Fri, 19 Apr 2024 11:47:02 -0600 Subject: [PATCH 04/10] Fixed alpha_test_value --- src/graphic/Fast3D/gfx_direct3d11.cpp | 7 +++- src/graphic/Fast3D/gfx_direct3d_common.cpp | 7 +++- src/graphic/Fast3D/gfx_metal.cpp | 9 +++-- src/graphic/Fast3D/gfx_metal_shader.cpp | 38 +++++++++++++++++----- src/graphic/Fast3D/gfx_opengl.cpp | 23 +++++++++++-- src/graphic/Fast3D/gfx_pc.cpp | 17 ++++++---- src/graphic/Fast3D/gfx_pc.h | 3 +- src/graphic/Fast3D/gfx_rendering_api.h | 2 +- 8 files changed, 84 insertions(+), 22 deletions(-) diff --git a/src/graphic/Fast3D/gfx_direct3d11.cpp b/src/graphic/Fast3D/gfx_direct3d11.cpp index 811f07733..a0cdfbdd9 100644 --- a/src/graphic/Fast3D/gfx_direct3d11.cpp +++ b/src/graphic/Fast3D/gfx_direct3d11.cpp @@ -42,6 +42,7 @@ namespace { struct PerFrameCB { uint32_t noise_frame; float noise_scale; + float alpha_test_value; uint32_t padding[2]; // constant buffers must be multiples of 16 bytes in size }; @@ -920,7 +921,7 @@ static void gfx_d3d11_update_framebuffer_parameters(int fb_id, uint32_t width, u fb.msaa_level = msaa_level; } -void gfx_d3d11_start_draw_to_framebuffer(int fb_id, float noise_scale) { +void gfx_d3d11_start_draw_to_framebuffer(int fb_id, float noise_scale, float alpha_test_value) { Framebuffer& fb = d3d.framebuffers[fb_id]; d3d.render_target_height = d3d.textures[fb.texture_id].height; @@ -933,6 +934,10 @@ void gfx_d3d11_start_draw_to_framebuffer(int fb_id, float noise_scale) { d3d.per_frame_cb_data.noise_scale = 1.0f / noise_scale; } + if (alpha_test_value != 0.0f) { + d3d.per_frame_cb_data.alpha_test_value = alpha_test_value; + } + D3D11_MAPPED_SUBRESOURCE ms; ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE)); d3d.context->Map(d3d.per_frame_cb.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &ms); diff --git a/src/graphic/Fast3D/gfx_direct3d_common.cpp b/src/graphic/Fast3D/gfx_direct3d_common.cpp index 211e65709..df24c9e13 100644 --- a/src/graphic/Fast3D/gfx_direct3d_common.cpp +++ b/src/graphic/Fast3D/gfx_direct3d_common.cpp @@ -194,6 +194,7 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f append_line(buf, &len, "cbuffer PerFrameCB : register(b0) {"); append_line(buf, &len, " uint noise_frame;"); append_line(buf, &len, " float noise_scale;"); + append_line(buf, &len, " float alpha_test_value;"); append_line(buf, &len, "}"); append_line(buf, &len, "float3 colorDither(in float _noise_val, in float3 _color)"); @@ -448,6 +449,10 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f append_line(buf, &len, " texel.a = alphaDither(random(float3(floor(screenSpace.xy * noise_scale), " "float(noise_frame))), texel.a);"); + } else if (cc_features.opt_noise) { + append_line(fs_buf, &fs_len, + " texel.rgb = colorDither(random(float3(floor(screenSpace.xy * noise_scale), float(frame_count))), " + " texel.rgb);"); } if (cc_features.opt_alpha) { @@ -455,7 +460,7 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f if (cc_features.opt_alpha_threshold) { append_line(buf, &len, "alphaValue = clamp(alphaValue, 0.0, 1.0);"); - append_line(buf, &len, "if (alphaValue < alphaTestValue) discard;"); + append_line(buf, &len, "if (alphaValue < alpha_test_value) discard;"); } if (cc_features.opt_invisible) { append_line(buf, &len, " texel.a = 0.0;"); diff --git a/src/graphic/Fast3D/gfx_metal.cpp b/src/graphic/Fast3D/gfx_metal.cpp index 4c1a287f6..bc8803f9a 100644 --- a/src/graphic/Fast3D/gfx_metal.cpp +++ b/src/graphic/Fast3D/gfx_metal.cpp @@ -114,6 +114,7 @@ struct FramebufferMetal { struct FrameUniforms { simd::int1 frameCount; simd::float1 noiseScale; + simd::float1 alphaTestValue; }; struct CoordUniforms { @@ -274,7 +275,7 @@ static void gfx_metal_init(void) { struct CoordUniforms { uint2 coords[1024]; }; - + kernel void depthKernel(depth2d depth_texture [[ texture(0) ]], constant CoordUniforms& query_coords [[ buffer(0) ]], device float* output_values [[ buffer(1) ]], @@ -914,7 +915,7 @@ static void gfx_metal_update_framebuffer_parameters(int fb_id, uint32_t width, u autorelease_pool->release(); } -void gfx_metal_start_draw_to_framebuffer(int fb_id, float noise_scale) { +void gfx_metal_start_draw_to_framebuffer(int fb_id, float noise_scale, float alpha_test_value) { FramebufferMetal& fb = mctx.framebuffers[fb_id]; mctx.render_target_height = mctx.textures[fb.texture_id].height; @@ -939,6 +940,10 @@ void gfx_metal_start_draw_to_framebuffer(int fb_id, float noise_scale) { mctx.frame_uniforms.noiseScale = 1.0f / noise_scale; } + if (alpha_test_value != 0.0f) { + mctx.frame_uniforms.alphaTestValue = alpha_test_value; + } + memcpy(mctx.frame_uniform_buffer->contents(), &mctx.frame_uniforms, sizeof(FrameUniforms)); } diff --git a/src/graphic/Fast3D/gfx_metal_shader.cpp b/src/graphic/Fast3D/gfx_metal_shader.cpp index 8757ab586..e0e7a3bbf 100644 --- a/src/graphic/Fast3D/gfx_metal_shader.cpp +++ b/src/graphic/Fast3D/gfx_metal_shader.cpp @@ -140,6 +140,7 @@ MTL::VertexDescriptor* gfx_metal_build_shader(char buf[8192], size_t& num_floats append_line(buf, &len, "struct FrameUniforms {"); append_line(buf, &len, " int frameCount;"); append_line(buf, &len, " float noiseScale;"); + append_line(buf, &len, " float alphaTestValue;"); append_line(buf, &len, "};"); // end uniforms struct @@ -293,6 +294,21 @@ MTL::VertexDescriptor* gfx_metal_build_shader(char buf[8192], size_t& num_floats append_line(buf, &len, "}"); } + append_line(buf, &len, "float3 colorDither(float _noise_val, float3 _color) {"); + append_line(buf, &len, " float3 _noise = float3(_noise_val, _noise_val, _noise_val);"); + append_line(buf, &len, " float3 threshold = 7.0 / 255.0 * (_noise - 0.5);"); + append_line(buf, &len, " _color = clamp(_color + threshold, 0.0, 1.0);"); + append_line(buf, &len, " _color.rgb = round(_color.rgb * 32.0) / 32.0;"); + append_line(buf, &len, " return _color;"); + append_line(buf, &len, "}"); + + append_line(buf, &len, "float alphaDither(float _noise, float _alpha) {"); + append_line(buf, &len, " float threshold = 7.0 / 255.0 * (_noise - 0.5);"); + append_line(buf, &len, " _alpha = clamp(_alpha + threshold, 0.0, 1.0);"); + append_line(buf, &len, " _alpha = round(_alpha * 32.0) / 32.0;"); + append_line(buf, &len, " return _alpha;"); + append_line(buf, &len, "}"); + append_line(buf, &len, "float random(float3 value) {"); append_line(buf, &len, " float random = dot(sin(value), float3(12.9898, 78.233, 37.719));"); append_line(buf, &len, " return fract(sin(random) * 143758.5453);"); @@ -415,22 +431,28 @@ MTL::VertexDescriptor* gfx_metal_build_shader(char buf[8192], size_t& num_floats append_line(buf, &len, " if (texel.w > 0.19) texel.w = 1.0; else discard_fragment();"); } - if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(buf, &len, " float2 coords = in.position.xy * frameUniforms.noiseScale;"); - append_line(buf, &len, - " texel.w *= floor(fast::clamp(random(float3(floor(coords), float(frameUniforms.frameCount))) + " - "texel.w, 0.0, 1.0));"); - } - if (cc_features.opt_grayscale) { append_line(buf, &len, " float intensity = (texel.x + texel.y + texel.z) / 3.0;"); append_line(buf, &len, " float3 new_texel = in.grayscale.xyz * intensity;"); append_line(buf, &len, " texel.xyz = mix(texel.xyz, new_texel, in.grayscale.w);"); } + if (cc_features.opt_alpha && cc_features.opt_noise) { + append_line(buf, &len, + " texel.w = alphaDither(random(float3(floor(in.position.xy * frameUniforms.noiseScale), " + "float(frameUniforms.frameCount))), texel.w);"); + } else if (cc_features.opt_noise) { + append_line(buf, &len, + " texel.rgb = colorDither(random(float3(floor(in.position.xy * frameUniforms.noiseScale), float(frameUniforms.frameCount))), " + " texel.rgb);"); + } + if (cc_features.opt_alpha) { + append_line(buf, &len, " float alphaValue = texel.w;"); + if (cc_features.opt_alpha_threshold) { - append_line(buf, &len, " if (texel.w < 8.0 / 256.0) discard_fragment();"); + append_line(buf, &len, " alphaValue = clamp(alphaValue, 0.0, 1.0);"); + append_line(buf, &len, " if (alphaValue < frameUniforms.alphaTestValue) discard_fragment();"); } if (cc_features.opt_invisible) { append_line(buf, &len, " texel.w = 0.0;"); diff --git a/src/graphic/Fast3D/gfx_opengl.cpp b/src/graphic/Fast3D/gfx_opengl.cpp index ba1c1cd9f..12c0cd802 100644 --- a/src/graphic/Fast3D/gfx_opengl.cpp +++ b/src/graphic/Fast3D/gfx_opengl.cpp @@ -60,8 +60,10 @@ struct ShaderProgram { GLint attrib_locations[16]; uint8_t attrib_sizes[16]; uint8_t num_attribs; + bool used_alpha_threshold; GLint frame_count_location; GLint noise_scale_location; + GLint alpha_test_val_location; }; struct Framebuffer { @@ -85,6 +87,7 @@ static uint32_t frame_count; static vector framebuffers; static size_t current_framebuffer; static float current_noise_scale; +static float current_alpha_test_value = 0.0f; static FilteringMode current_filter_mode = FILTER_THREE_POINT; GLint max_msaa_level = 1; @@ -120,6 +123,9 @@ static void gfx_opengl_vertex_array_set_attribs(struct ShaderProgram* prg) { static void gfx_opengl_set_uniforms(struct ShaderProgram* prg) { glUniform1i(prg->frame_count_location, frame_count); glUniform1f(prg->noise_scale_location, current_noise_scale); + if (prg->used_alpha_threshold) { + glUniform1f(prg->alpha_test_val_location, current_alpha_test_value); + } } static void gfx_opengl_unload_shader(struct ShaderProgram* old_prg) { @@ -415,6 +421,11 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad append_line(fs_buf, &fs_len, "uniform sampler2D uTexBlend1;"); } + if (cc_features.opt_alpha_threshold) { + append_line(fs_buf, &fs_len, "uniform float alphaTestValue;"); + append_line(fs_buf, &fs_len, "#define WRAP(x, low, high) (mod((x)-(low), (high)-(low)) + (low));"); + } + append_line(fs_buf, &fs_len, "uniform int frame_count;"); append_line(fs_buf, &fs_len, "uniform float noise_scale;"); @@ -586,7 +597,6 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad } if (cc_features.opt_alpha) { - append_line(fs_buf, &fs_len, "float cvg = 1.0;"); append_line(fs_buf, &fs_len, "float alphaValue = texel.a;"); if (cc_features.opt_alpha_threshold) { @@ -715,6 +725,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad prg->frame_count_location = glGetUniformLocation(shader_program, "frame_count"); prg->noise_scale_location = glGetUniformLocation(shader_program, "noise_scale"); + prg->alpha_test_val_location = glGetUniformLocation(shader_program, "alphaTestValue"); gfx_opengl_load_shader(prg); @@ -743,6 +754,13 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad glUniform1i(sampler_location, 5); } + if(cc_features.opt_alpha_cvg_sel || cc_features.opt_alpha_threshold) { + prg->alpha_test_val_location = glGetUniformLocation(shader_program, "alphaTestValue"); + prg->used_alpha_threshold = true; + } else { + prg->used_alpha_threshold = false; + } + return prg; } @@ -1003,9 +1021,10 @@ static void gfx_opengl_update_framebuffer_parameters(int fb_id, uint32_t width, fb.invert_y = opengl_invert_y; } -void gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale) { +void gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale, float alpha_test_value) { Framebuffer& fb = framebuffers[fb_id]; + current_alpha_test_value = alpha_test_value; if (noise_scale != 0.0f) { current_noise_scale = 1.0f / noise_scale; } diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index 8acd50b63..02cfe2741 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -1421,6 +1421,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo bool invisible = (g_rdp.other_mode_l & (3 << 24)) == (G_BL_0 << 24) && (g_rdp.other_mode_l & (3 << 20)) == (G_BL_CLR_MEM << 20); bool use_grayscale = g_rdp.grayscale; + g_rdp.alpha_test_value = 0.0f; if (texture_edge) { use_alpha = true; @@ -1443,6 +1444,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo } if (alpha_threshold) { cc_options |= (uint64_t)SHADER_OPT_ALPHA_THRESHOLD; + g_rdp.alpha_test_value = g_rdp.blend_color.a; } if (invisible) { cc_options |= (uint64_t)SHADER_OPT_INVISIBLE; @@ -2187,7 +2189,10 @@ static void gfx_dp_set_fog_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { } static void gfx_dp_set_blend_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - // TODO: Implement this command.. + g_rdp.blend_color.r = r; + g_rdp.blend_color.g = g; + g_rdp.blend_color.b = b; + g_rdp.blend_color.a = a; } static void gfx_dp_set_fill_color(uint32_t packed_color) { @@ -3294,7 +3299,7 @@ bool gfx_reset_fb_handler_custom(Gfx** cmd0) { gfx_flush(); fbActive = 0; gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, - gfx_calculate_noise_scale()); + gfx_calculate_noise_scale(), g_rdp.alpha_test_value); return false; } @@ -3893,7 +3898,7 @@ void gfx_run(Gfx* commands, const std::unordered_map& mtx_replacemen !game_renders_to_framebuffer); gfx_rapi->start_frame(); gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, - gfx_calculate_noise_scale()); + gfx_calculate_noise_scale(), g_rdp.alpha_test_value); gfx_rapi->clear_framebuffer(); g_rdp.viewport_or_scissor_changed = true; rendering_state.viewport = {}; @@ -3918,7 +3923,7 @@ void gfx_run(Gfx* commands, const std::unordered_map& mtx_replacemen currentDir = std::stack(); if (game_renders_to_framebuffer) { - gfx_rapi->start_draw_to_framebuffer(0, 1); + gfx_rapi->start_draw_to_framebuffer(0, 1, 0); gfx_rapi->clear_framebuffer(); if (gfx_msaa_level > 1) { @@ -3974,7 +3979,7 @@ extern "C" int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t } void gfx_set_framebuffer(int fb, float noise_scale) { - gfx_rapi->start_draw_to_framebuffer(fb, noise_scale); + gfx_rapi->start_draw_to_framebuffer(fb, noise_scale, g_rdp.alpha_test_value); gfx_rapi->clear_framebuffer(); } @@ -4022,7 +4027,7 @@ void gfx_copy_framebuffer(int fb_dst_id, int fb_src_id, bool copyOnce, bool* has } void gfx_reset_framebuffer() { - gfx_rapi->start_draw_to_framebuffer(0, gfx_calculate_noise_scale()); + gfx_rapi->start_draw_to_framebuffer(0, gfx_calculate_noise_scale(), g_rdp.alpha_test_value); gfx_rapi->clear_framebuffer(); } diff --git a/src/graphic/Fast3D/gfx_pc.h b/src/graphic/Fast3D/gfx_pc.h index 757952ef8..402241d53 100644 --- a/src/graphic/Fast3D/gfx_pc.h +++ b/src/graphic/Fast3D/gfx_pc.h @@ -185,8 +185,9 @@ struct RDP { bool grayscale; uint8_t prim_lod_fraction; - struct RGBA env_color, prim_color, fog_color, fill_color, grayscale_color; + struct RGBA env_color, blend_color, prim_color, fog_color, fill_color, grayscale_color; struct XYWidthHeight viewport, scissor; + float alpha_test_value; bool viewport_or_scissor_changed; void* z_buf_address; void* color_image_address; diff --git a/src/graphic/Fast3D/gfx_rendering_api.h b/src/graphic/Fast3D/gfx_rendering_api.h index 01959d2f4..add7c4508 100644 --- a/src/graphic/Fast3D/gfx_rendering_api.h +++ b/src/graphic/Fast3D/gfx_rendering_api.h @@ -57,7 +57,7 @@ struct GfxRenderingAPI { void (*update_framebuffer_parameters)(int fb_id, uint32_t width, uint32_t height, uint32_t msaa_level, bool opengl_invert_y, bool render_target, bool has_depth_buffer, bool can_extract_depth); - void (*start_draw_to_framebuffer)(int fb_id, float noise_scale); + void (*start_draw_to_framebuffer)(int fb_id, float noise_scale, float alpha_test_value); void (*copy_framebuffer)(int fb_dst_id, int fb_src_id, int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1); void (*clear_framebuffer)(void); From a052299e239d1e5ce0714e75f46c2fbe7530f4c5 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Fri, 19 Apr 2024 11:48:15 -0600 Subject: [PATCH 05/10] Fixed gfx_calculate_noise_scale --- src/graphic/Fast3D/gfx_pc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index 02cfe2741..4afd6f460 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -3292,7 +3292,7 @@ bool gfx_set_fb_handler_custom(Gfx** cmd0) { } float gfx_calculate_noise_scale() { - return ((float)gfx_current_dimensions.height / SCREEN_HEIGHT) * 0.5f; + return ((float)gfx_current_game_window_viewport.height / SCREEN_HEIGHT) * 0.5f; } bool gfx_reset_fb_handler_custom(Gfx** cmd0) { From 61489a4619261276113751e34e9ff4343d73957b Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Fri, 19 Apr 2024 13:36:35 -0600 Subject: [PATCH 06/10] Removed opt_alpha_cvg_sel leftover --- src/graphic/Fast3D/gfx_opengl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphic/Fast3D/gfx_opengl.cpp b/src/graphic/Fast3D/gfx_opengl.cpp index 12c0cd802..c0723be57 100644 --- a/src/graphic/Fast3D/gfx_opengl.cpp +++ b/src/graphic/Fast3D/gfx_opengl.cpp @@ -754,7 +754,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad glUniform1i(sampler_location, 5); } - if(cc_features.opt_alpha_cvg_sel || cc_features.opt_alpha_threshold) { + if(cc_features.opt_alpha_threshold) { prg->alpha_test_val_location = glGetUniformLocation(shader_program, "alphaTestValue"); prg->used_alpha_threshold = true; } else { From 1850b5f6328c9909c668daa1a5e11807261ae55a Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Fri, 19 Apr 2024 13:42:49 -0600 Subject: [PATCH 07/10] Fixed wrong variable --- src/graphic/Fast3D/gfx_direct3d_common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphic/Fast3D/gfx_direct3d_common.cpp b/src/graphic/Fast3D/gfx_direct3d_common.cpp index df24c9e13..fb9dc88a2 100644 --- a/src/graphic/Fast3D/gfx_direct3d_common.cpp +++ b/src/graphic/Fast3D/gfx_direct3d_common.cpp @@ -450,7 +450,7 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f " texel.a = alphaDither(random(float3(floor(screenSpace.xy * noise_scale), " "float(noise_frame))), texel.a);"); } else if (cc_features.opt_noise) { - append_line(fs_buf, &fs_len, + append_line(buf, &len, " texel.rgb = colorDither(random(float3(floor(screenSpace.xy * noise_scale), float(frame_count))), " " texel.rgb);"); } From 9a2a8b9cf7e20c150f7dcac2ec0cc04646a5ba04 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Sun, 21 Apr 2024 14:40:01 -0600 Subject: [PATCH 08/10] Fixed tidy --- src/graphic/Fast3D/gfx_direct3d_common.cpp | 7 ++++--- src/graphic/Fast3D/gfx_metal_shader.cpp | 3 ++- src/graphic/Fast3D/gfx_opengl.cpp | 2 +- src/graphic/Fast3D/gfx_pc.cpp | 14 +++++++------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/graphic/Fast3D/gfx_direct3d_common.cpp b/src/graphic/Fast3D/gfx_direct3d_common.cpp index fb9dc88a2..b0bb3d16b 100644 --- a/src/graphic/Fast3D/gfx_direct3d_common.cpp +++ b/src/graphic/Fast3D/gfx_direct3d_common.cpp @@ -450,9 +450,10 @@ void gfx_direct3d_common_build_shader(char buf[8192], size_t& len, size_t& num_f " texel.a = alphaDither(random(float3(floor(screenSpace.xy * noise_scale), " "float(noise_frame))), texel.a);"); } else if (cc_features.opt_noise) { - append_line(buf, &len, - " texel.rgb = colorDither(random(float3(floor(screenSpace.xy * noise_scale), float(frame_count))), " - " texel.rgb);"); + append_line( + buf, &len, + " texel.rgb = colorDither(random(float3(floor(screenSpace.xy * noise_scale), float(frame_count))), " + " texel.rgb);"); } if (cc_features.opt_alpha) { diff --git a/src/graphic/Fast3D/gfx_metal_shader.cpp b/src/graphic/Fast3D/gfx_metal_shader.cpp index e0e7a3bbf..8fb488792 100644 --- a/src/graphic/Fast3D/gfx_metal_shader.cpp +++ b/src/graphic/Fast3D/gfx_metal_shader.cpp @@ -443,7 +443,8 @@ MTL::VertexDescriptor* gfx_metal_build_shader(char buf[8192], size_t& num_floats "float(frameUniforms.frameCount))), texel.w);"); } else if (cc_features.opt_noise) { append_line(buf, &len, - " texel.rgb = colorDither(random(float3(floor(in.position.xy * frameUniforms.noiseScale), float(frameUniforms.frameCount))), " + " texel.rgb = colorDither(random(float3(floor(in.position.xy * frameUniforms.noiseScale), " + "float(frameUniforms.frameCount))), " " texel.rgb);"); } diff --git a/src/graphic/Fast3D/gfx_opengl.cpp b/src/graphic/Fast3D/gfx_opengl.cpp index c0723be57..051893e7e 100644 --- a/src/graphic/Fast3D/gfx_opengl.cpp +++ b/src/graphic/Fast3D/gfx_opengl.cpp @@ -754,7 +754,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad glUniform1i(sampler_location, 5); } - if(cc_features.opt_alpha_threshold) { + if (cc_features.opt_alpha_threshold) { prg->alpha_test_val_location = glGetUniformLocation(shader_program, "alphaTestValue"); prg->used_alpha_threshold = true; } else { diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index 4afd6f460..776813383 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -49,11 +49,11 @@ using namespace std; #define SUPPORT_CHECK(x) assert(x) // SCALE_M_N: upscale/downscale M-bit integer to N-bit -#define SCALE_5_8(VAL_) (((VAL_)*0xFF) / 0x1F) +#define SCALE_5_8(VAL_) (((VAL_) * 0xFF) / 0x1F) #define SCALE_8_5(VAL_) ((((VAL_) + 4) * 0x1F) / 0xFF) -#define SCALE_4_8(VAL_) ((VAL_)*0x11) +#define SCALE_4_8(VAL_) ((VAL_) * 0x11) #define SCALE_8_4(VAL_) ((VAL_) / 0x11) -#define SCALE_3_8(VAL_) ((VAL_)*0x24) +#define SCALE_3_8(VAL_) ((VAL_) * 0x24) #define SCALE_8_3(VAL_) ((VAL_) / 0x24) // Based off the current set native dimensions @@ -3298,8 +3298,8 @@ float gfx_calculate_noise_scale() { bool gfx_reset_fb_handler_custom(Gfx** cmd0) { gfx_flush(); fbActive = 0; - gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, - gfx_calculate_noise_scale(), g_rdp.alpha_test_value); + gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, gfx_calculate_noise_scale(), + g_rdp.alpha_test_value); return false; } @@ -3897,8 +3897,8 @@ void gfx_run(Gfx* commands, const std::unordered_map& mtx_replacemen gfx_current_window_dimensions.height, 1, false, true, true, !game_renders_to_framebuffer); gfx_rapi->start_frame(); - gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, - gfx_calculate_noise_scale(), g_rdp.alpha_test_value); + gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, gfx_calculate_noise_scale(), + g_rdp.alpha_test_value); gfx_rapi->clear_framebuffer(); g_rdp.viewport_or_scissor_changed = true; rendering_state.viewport = {}; From 84c0de757dced556263692d6c1e29c23f1dbf2ec Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Sun, 21 Apr 2024 15:08:45 -0600 Subject: [PATCH 09/10] Fixed tidy manually --- src/graphic/Fast3D/gfx_pc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index 776813383..5cd9dd8cf 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -49,11 +49,11 @@ using namespace std; #define SUPPORT_CHECK(x) assert(x) // SCALE_M_N: upscale/downscale M-bit integer to N-bit -#define SCALE_5_8(VAL_) (((VAL_) * 0xFF) / 0x1F) +#define SCALE_5_8(VAL_) (((VAL_)*0xFF) / 0x1F) #define SCALE_8_5(VAL_) ((((VAL_) + 4) * 0x1F) / 0xFF) -#define SCALE_4_8(VAL_) ((VAL_) * 0x11) +#define SCALE_4_8(VAL_) ((VAL_)*0x11) #define SCALE_8_4(VAL_) ((VAL_) / 0x11) -#define SCALE_3_8(VAL_) ((VAL_) * 0x24) +#define SCALE_3_8(VAL_) ((VAL_)*0x24) #define SCALE_8_3(VAL_) ((VAL_) / 0x24) // Based off the current set native dimensions From 1d43f3527ee14513fc8c0a90e89c1cbbcf8e5ae4 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Sun, 21 Apr 2024 15:30:59 -0600 Subject: [PATCH 10/10] Fixed gfx_calculate_noise_scale --- src/graphic/Fast3D/gfx_pc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index 5cd9dd8cf..e510db7e6 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -3292,7 +3292,7 @@ bool gfx_set_fb_handler_custom(Gfx** cmd0) { } float gfx_calculate_noise_scale() { - return ((float)gfx_current_game_window_viewport.height / SCREEN_HEIGHT) * 0.5f; + return ((float)gfx_current_dimensions.height / gfx_native_dimensions.height) * 0.5f; } bool gfx_reset_fb_handler_custom(Gfx** cmd0) {