Skip to content

Instantly share code, notes, and snippets.

@bqqbarbhg
Created February 16, 2021 19:19
Show Gist options
  • Select an option

  • Save bqqbarbhg/b9126445cf63c4571ef0e7e1daff5f8e to your computer and use it in GitHub Desktop.

Select an option

Save bqqbarbhg/b9126445cf63c4571ef0e7e1daff5f8e to your computer and use it in GitHub Desktop.
#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