Created
February 16, 2021 19:19
-
-
Save bqqbarbhg/b9126445cf63c4571ef0e7e1daff5f8e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "dof.h" | |
| #include <string.h> | |
| #include <stdint.h> | |
| #include <math.h> | |
| static float sample_chan(const dof_opts *opts, const dof_channel *chan, size_t x, size_t y) | |
| { | |
| return *(const float*)((const char*)chan->data + (y * opts->width + x) * chan->stride); | |
| } | |
| static void write_chan(const dof_opts *opts, const dof_mut_channel *chan, size_t x, size_t y, float v) | |
| { | |
| *(float*)((char*)chan->data + (y * opts->width + x) * chan->stride) = v; | |
| } | |
| static float sample_rgba(const dof_opts *opts, size_t i, size_t x, size_t y) | |
| { | |
| return sample_chan(opts, &opts->src_rgba[i], x, y); | |
| } | |
| static float sample_z(const dof_opts *opts, size_t x, size_t y) | |
| { | |
| return sample_chan(opts, &opts->src_z, x, y); | |
| } | |
| static void write_rgba(const dof_opts *opts, size_t i, size_t x, size_t y, float v) | |
| { | |
| write_chan(opts, &opts->dst_rgba[i], x, y, v); | |
| } | |
| static float blur_radius(const dof_opts *opts, float z) | |
| { | |
| return fminf(fmaxf(1.0f, z) / 150.0f, opts->max_blur); | |
| } | |
| static void init_chan(dof_channel *c) | |
| { | |
| if (c->stride == 0) c->stride = sizeof(float); | |
| } | |
| static void init_mut_chan(dof_mut_channel *c) | |
| { | |
| if (c->stride == 0) c->stride = sizeof(float); | |
| } | |
| void dof_apply(const dof_opts *opts, const dof_rect *rect) | |
| { | |
| dof_opts o = *opts; | |
| dof_rect r; | |
| if (rect) { | |
| r = *rect; | |
| } else { | |
| r.x_min = 0; | |
| r.x_max = o.width; | |
| r.y_min = 0; | |
| r.y_max = o.height; | |
| } | |
| for (size_t i = 0; i < 4; i++) { | |
| init_chan(&o.src_rgba[i]); | |
| init_mut_chan(&o.dst_rgba[i]); | |
| } | |
| init_chan(&o.src_z); | |
| int32_t kernel_sz = (int32_t)ceilf(o.max_blur); | |
| int32_t kernel_sz2 = kernel_sz*kernel_sz; | |
| for (size_t s_y = r.y_min; s_y < r.y_max; s_y++) | |
| for (size_t s_x = r.x_min; s_x < r.x_max; s_x++) | |
| { | |
| float sum[4] = { }; | |
| float weight = 0.0f; | |
| float s_z = sample_z(&o, s_x, s_y); | |
| float s_br = blur_radius(&o, s_z); | |
| for (int32_t dy = -kernel_sz; dy <= +kernel_sz; dy++) | |
| for (int32_t dx = -kernel_sz; dx <= +kernel_sz; dx++) | |
| { | |
| int32_t d2 = dx*dx + dy*dy; | |
| if (d2 > kernel_sz2) continue; | |
| size_t p_x = s_x + (size_t)dx, p_y = s_y + (size_t)dy; | |
| if (p_x >= o.width || p_y >= o.height) continue; | |
| float p_z = sample_z(&o, p_x, p_y); | |
| float p_br = blur_radius(&o, p_z); | |
| if (p_z > s_z) p_br = fminf(p_br, s_br); | |
| float w = 1.0f / (1.0f + p_br); | |
| if ((float)d2 > p_br) w = 0.0f; | |
| if (w > 0.000001f) { | |
| sum[0] += w * sample_rgba(&o, 0, p_x, p_y); | |
| sum[1] += w * sample_rgba(&o, 1, p_x, p_y); | |
| sum[2] += w * sample_rgba(&o, 2, p_x, p_y); | |
| sum[3] += w * sample_rgba(&o, 3, p_x, p_y); | |
| weight += w; | |
| } | |
| } | |
| sum[0] /= weight; | |
| sum[1] /= weight; | |
| sum[2] /= weight; | |
| sum[3] /= weight; | |
| write_rgba(&o, 0, s_x, s_y, sum[0]); | |
| write_rgba(&o, 1, s_x, s_y, sum[1]); | |
| write_rgba(&o, 2, s_x, s_y, sum[2]); | |
| write_rgba(&o, 3, s_x, s_y, sum[3]); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment