diff --git a/src/shaders/custom.c b/src/shaders/custom.c index a01fac10a5c9197b669dc868d5595d3985433110..9006f1002899b9707a239352751a87b22337ee23 100644 --- a/src/shaders/custom.c +++ b/src/shaders/custom.c @@ -62,6 +62,7 @@ struct custom_shader_hook { // Shader body itself + metadata struct bstr pass_body; float offset[2]; + bool offset_align; int comps; // Special expressions governing the output size and execution conditions @@ -284,13 +285,18 @@ static bool parse_hook(struct pl_context *ctx, struct bstr *body, } if (bstr_eatstart0(&line, "OFFSET")) { - float ox, oy; - if (bstr_sscanf(line, "%f %f", &ox, &oy) != 2) { - pl_err(ctx, "Error while parsing OFFSET!"); - return false; + line = bstr_strip(line); + if (bstr_equals0(line, "ALIGN")) { + out->offset_align = true; + } else { + float ox, oy; + if (bstr_sscanf(line, "%f %f", &ox, &oy) != 2) { + pl_err(ctx, "Error while parsing OFFSET!"); + return false; + } + out->offset[0] = ox; + out->offset[1] = oy; } - out->offset[0] = ox; - out->offset[1] = oy; continue; } @@ -750,13 +756,11 @@ static double prng_step(uint64_t s[4]) } static bool bind_pass_tex(struct pl_shader *sh, struct bstr name, - const struct pass_tex *ptex) + const struct pass_tex *ptex, + const struct pl_rect2df *rect) { - // Note: We bind the whole texture, rather than params->rect, because - // user shaders in general are not designed to handle cropped input - // textures. ident_t id, pos, size, pt; - id = sh_bind(sh, ptex->tex, "hook_tex", NULL, &pos, &size, &pt); + id = sh_bind(sh, ptex->tex, "hook_tex", rect, &pos, &size, &pt); if (!id) return false; @@ -946,7 +950,25 @@ static struct pl_hook_res hook_hook(void *priv, const struct pl_hook_params *par for (int j = 0; j < p->num_pass_textures; j++) { if (bstr_equals(texname, p->pass_textures[j].name)) { - if (!bind_pass_tex(sh, texname, &p->pass_textures[j])) + // Note: We bind the whole texture, rather than + // params->rect, because user shaders in general are not + // designed to handle cropped input textures. + const struct pass_tex *ptex = &p->pass_textures[j]; + struct pl_rect2df rect = { + 0, 0, ptex->tex->params.w, ptex->tex->params.h, + }; + + if (hook->offset_align && bstr_equals(texname, stage)) { + float sx = pl_rect_w(params->rect) / pl_rect_w(params->src_rect), + sy = pl_rect_h(params->rect) / pl_rect_h(params->src_rect), + ox = params->rect.x0 - sx * params->src_rect.x0, + oy = params->rect.y0 - sy * params->src_rect.y0; + + PL_TRACE(p, "Aligning plane with ref: %f %f", ox, oy); + pl_rect2df_offset(&rect, ox, oy); + } + + if (!bind_pass_tex(sh, texname, &p->pass_textures[j], &rect)) goto error; goto next_bind; } @@ -1043,6 +1065,15 @@ static struct pl_hook_res hook_hook(void *priv, const struct pl_hook_params *par y0 + sy * pl_rect_h(params->rect), }; + if (hook->offset_align) { + float rx = pl_rect_w(new_rect) / pl_rect_w(params->src_rect), + ry = pl_rect_h(new_rect) / pl_rect_h(params->src_rect), + ox = rx * params->src_rect.x0 - sx * params->rect.x0, + oy = ry * params->src_rect.y0 - sy * params->rect.y0; + + pl_rect2df_offset(&new_rect, ox, oy); + } + // Save the result of this shader invocation struct pass_tex ptex = { .name = hook->save_tex.start ? hook->save_tex : stage,