Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented dither noise #492

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/graphic/Fast3D/gfx_direct3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down
32 changes: 29 additions & 3 deletions src/graphic/Fast3D/gfx_direct3d_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,24 @@ 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)");
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) {");
Expand Down Expand Up @@ -428,14 +446,22 @@ 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);");
} 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);");
}

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 < alpha_test_value) discard;");
}
if (cc_features.opt_invisible) {
append_line(buf, &len, " texel.a = 0.0;");
Expand Down
9 changes: 7 additions & 2 deletions src/graphic/Fast3D/gfx_metal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ struct FramebufferMetal {
struct FrameUniforms {
simd::int1 frameCount;
simd::float1 noiseScale;
simd::float1 alphaTestValue;
};

struct CoordUniforms {
Expand Down Expand Up @@ -274,7 +275,7 @@ static void gfx_metal_init(void) {
struct CoordUniforms {
uint2 coords[1024];
};

kernel void depthKernel(depth2d<float, access::read> depth_texture [[ texture(0) ]],
constant CoordUniforms& query_coords [[ buffer(0) ]],
device float* output_values [[ buffer(1) ]],
Expand Down Expand Up @@ -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;

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

Expand Down
39 changes: 31 additions & 8 deletions src/graphic/Fast3D/gfx_metal_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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);");
Expand Down Expand Up @@ -415,22 +431,29 @@ 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;");
Expand Down
51 changes: 47 additions & 4 deletions src/graphic/Fast3D/gfx_opengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -85,6 +87,7 @@ static uint32_t frame_count;
static vector<Framebuffer> 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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -415,9 +421,30 @@ 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;");

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);");
Expand Down Expand Up @@ -554,9 +581,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);");
} else if (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));");
"texel.rgb = colorDither(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))), "
"texel.rgb);");
}
Comment on lines 583 to 591
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least from what I can see in MM, it is possible for aplha dithering and color dithering to be applied at the same time. This if / if else does not allow that currently.

We may even need to split opt_noise into two values, or something so that we can control which is used.


if (cc_features.opt_grayscale) {
Expand All @@ -566,8 +597,11 @@ 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 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;");
KiritoDv marked this conversation as resolved.
Show resolved Hide resolved
}
if (cc_features.opt_invisible) {
append_line(fs_buf, &fs_len, "texel.a = 0.0;");
Expand Down Expand Up @@ -691,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);

Expand Down Expand Up @@ -719,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_threshold) {
prg->alpha_test_val_location = glGetUniformLocation(shader_program, "alphaTestValue");
prg->used_alpha_threshold = true;
} else {
prg->used_alpha_threshold = false;
}

return prg;
}

Expand Down Expand Up @@ -979,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;
}
Expand Down
Loading
Loading