MetaCoreEngineV2/rpcore/shader/includes/upsampling.inc.glsl
2026-01-13 17:06:06 +08:00

143 lines
5.6 KiB
GLSL

/**
*
* RenderPipeline
*
* Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#pragma once
#pragma include "includes/color_spaces.inc.glsl"
float mitchell_netravali_weights(float x)
{
// Mitchell Netravali Reconstruction Filter
// cubic B-spline
// const float b = 1.0, c = 0.0;
// recommended
// const float b = 1.0 / 3.0, c = 1.0 / 3.0;
// Catmull-Rom spline
const float b = 0.0, c = 1.0 / 2.0;
float ax = abs(x);
return (ax < 1.0) ?
((12.0 - 9.0 * b - 6.0 * c) * ax * ax * ax +
(-18.0 + 12.0 * b + 6.0 * c) * ax * ax + (6.0 - 2.0 * b)) / 6.0
: ((ax >= 1.0) && (ax < 2.0)) ?
((-b - 6.0 * c) * ax * ax * ax + (6.0 * b + 30.0 * c) * ax * ax +
(-12.0 * b - 48.0 * c) * ax + (8.0 * b + 24.0 * c)) / 6.0
: 0.0;
}
vec4 sample_color(sampler2D tex, vec2 uv) {
return saturate(textureLod(tex, uv, 0));
}
// Based on:
// http://glslsandbox.com/e#14615.1
vec4 bicubic_filter(sampler2D tex, vec2 uv)
{
vec2 px = 1.0 / textureSize(tex, 0).xy;
vec2 f = fract(uv / px);
vec2 texel = (uv / px - f + 0.5) * px;
vec4 weights = vec4(mitchell_netravali_weights(1.0 + f.x),
mitchell_netravali_weights(f.x),
mitchell_netravali_weights(1.0 - f.x),
mitchell_netravali_weights(2.0 - f.x));
vec4 t1 =
sample_color(tex, texel + vec2(-px.x, -px.y)) * weights.x +
sample_color(tex, texel + vec2(0.0, -px.y)) * weights.y +
sample_color(tex, texel + vec2(px.x, -px.y)) * weights.z +
sample_color(tex, texel + vec2(2.0 * px.x, -px.y)) * weights.w;
vec4 t2 =
sample_color(tex, texel + vec2(-px.x, 0.0)) * weights.x +
sample_color(tex, texel + vec2(0.0)) * weights.y +
sample_color(tex, texel + vec2(px.x, 0.0)) * weights.z +
sample_color(tex, texel + vec2(2.0 * px.x, 0.0)) * weights.w;
vec4 t3 =
sample_color(tex, texel + vec2(-px.x, px.y)) * weights.x +
sample_color(tex, texel + vec2(0.0, px.y)) * weights.y +
sample_color(tex, texel + vec2(px.x, px.y)) * weights.z +
sample_color(tex, texel + vec2(2.0 * px.x, px.y)) * weights.w;
vec4 t4 =
sample_color(tex, texel + vec2(-px.x, 2.0 * px.y)) * weights.x +
sample_color(tex, texel + vec2(0.0, 2.0 * px.y)) * weights.y +
sample_color(tex, texel + vec2(px.x, 2.0 * px.y)) * weights.z +
sample_color(tex, texel + vec2(2.0 * px.x, 2.0 * px.y)) * weights.w;
return mitchell_netravali_weights(1.0 + f.y) * t1 +
mitchell_netravali_weights(f.y) * t2 +
mitchell_netravali_weights(1.0 - f.y) * t3 +
mitchell_netravali_weights(2.0 - f.y) * t4;
}
// Simple bilinear filter
vec4 bilinear_filter(sampler2D tex, vec2 uv) {
vec2 pixel_size = 1.0 / textureSize(tex, 0).xy;
vec4 color = vec4(0);
float radius = 0.5;
color += sample_color(tex, uv + vec2(-radius, radius) * pixel_size);
color += sample_color(tex, uv + vec2(radius, radius) * pixel_size);
color += sample_color(tex, uv + vec2(-radius, -radius) * pixel_size);
color += sample_color(tex, uv + vec2(radius, -radius) * pixel_size);
return color * 0.25;
}
// Directional filter with a small sharpen kernel
vec4 directional_filter(sampler2D tex, vec2 uv) {
vec2 pixel_size = 1.0 / textureSize(tex, 0).xy;
float radius = 1.0;
vec4 color_nw = sample_color(tex, uv + vec2(-radius, -radius) * pixel_size);
vec4 color_ne = sample_color(tex, uv + vec2(radius, -radius) * pixel_size);
vec4 color_sw = sample_color(tex, uv + vec2(-radius, radius) * pixel_size);
vec4 color_se = sample_color(tex, uv + vec2(radius, radius) * pixel_size);
vec4 color = (color_nw + color_ne + color_sw + color_se) * 0.25;
float luma_nw = get_luminance(color_nw.xyz);
float luma_ne = get_luminance(color_ne.xyz) + 1e-5;
float luma_sw = get_luminance(color_sw.xyz);
float luma_se = get_luminance(color_se.xyz);
float center_luminance = get_luminance(color.xyz);
float uv_offs = saturate(center_luminance) * 2 - 1;
float diag_bl_tr = luma_sw - luma_ne;
float diag_br_tl = luma_se - luma_nw;
vec2 direction = normalize(vec2(diag_bl_tr + diag_br_tl, diag_bl_tr - diag_br_tl) + 1e-7);
vec2 direction_inv = vec2(-direction.y, direction.x);
uv_offs = 1 - ((1 - uv_offs) * (1 - uv_offs));
vec2 uv_offset = uv + direction_inv * pixel_size * abs(uv_offs) * -0.125;
vec4 color_n = sample_color(tex, uv_offset - direction * 0.125 * pixel_size);
vec4 color_p = sample_color(tex, uv_offset + direction * 0.125 * pixel_size);
const float sharpness = 0.9;
return (color_n + color_p) * ((sharpness + 1.0) * 0.5) - color * sharpness;
}