It has to do with the shaders you’re mixing and the order you’re mixing them in. That NTSC shader does some funky stuff to the scaling of the image and then bigblur does some more funky stuff and the results are unpredictable.
Bigblur also needs some modification to allow for putting shaders in front of it, as it currently always loads the raw core output for the center image:
// A recreation of the blur border commonly used for portrait cell phone videos
// Created by hunterk
// License: public domain
#pragma parameter aspect_x "Aspect Ratio Numerator" 64.0 1.0 256. 1.0
#pragma parameter aspect_y "Aspect Ratio Denominator" 49.0 1.0 256. 1.0
#pragma parameter ZOOM "Border Zoom" 1.5 0.5 10 0.5
#pragma parameter integer_scale "Force Integer Scaling" 1.0 0.0 1.0 1.0
#pragma parameter overscale "Integer Overscale" 0.0 0.0 1.0 1.0
#pragma parameter scanline_toggle "Scanline Toggle" 0.0 0.0 1.0 1.0
#pragma parameter interp_toggle "Sharpen Linear Scaling" 0.0 0.0 1.0 1.0
#pragma parameter THICKNESS "Scanline Thickness" 2.0 1.0 12.0 1.0
#pragma parameter DARKNESS "Scanline Darkness" 0.35 0.0 1.0 0.05
#ifdef PARAMETER_UNIFORM
uniform float aspect_x;
uniform float aspect_y;
uniform float ZOOM;
uniform float integer_scale;
uniform float overscale;
uniform float scanline_toggle;
uniform float THICKNESS;
uniform float DARKNESS;
uniform float interp_toggle;
#else
#define aspect_x 64.0
#define aspect_y 49.0
#define ZOOM 1.5
#define integer_scale 1.0
#define overscale 0.0
#define scanline_toggle 0.0
#define THICKNESS 2.0
#define DARKNESS 0.35
#define interp_toggle 0.0
#endif
// END PARAMETERS //
#include "../../compat_includes.inc"
INITIALIZE_PASSPREV(3, 0)
uniform COMPAT_Texture2D(decal) : TEXUNIT0;
uniform float4x4 modelViewProj;
struct out_vertex
{
float4 position : COMPAT_POS;
float2 texCoord : TEXCOORD;
float2 tex_border : TEXCOORD1;
};
out_vertex main_vertex(COMPAT_IN_VERTEX)
{
#ifdef HLSL_4
float4 position = VIN.position;
float2 texCoord = VIN.texCoord;
float2 t1 = VIN.t1;
#endif
out_vertex OUT;
OUT.position = mul(modelViewProj, position);
float2 out_res = COMPAT_output_size;
float2 corrected_size = COMPAT_video_size * float2(aspect_x / aspect_y, 1.0)
* float2(COMPAT_video_size.y / COMPAT_video_size.x, 1.0);
float full_scale = (integer_scale > 0.5) ? floor(COMPAT_output_size.y /
COMPAT_video_size.y) + overscale : COMPAT_output_size.y / COMPAT_video_size.y;
float2 scale = (COMPAT_output_size / corrected_size) / full_scale;
float2 middle = float2(0.49999, 0.49999) * COMPAT_video_size / COMPAT_texture_size;
float2 diff = texCoord.xy - middle;
OUT.texCoord = middle + diff * scale;
float2 zoom_coord = (((texCoord - middle) / ZOOM) * float2(COMPAT_output_size.x / COMPAT_output_size.y, 1.0)
/ float2(aspect_x / aspect_y, 1.0)) + middle;
OUT.tex_border = zoom_coord;
return OUT;
}
#define fragcoord (tex.xy * (texture_size.xy/video_size.xy))
float4 scanlines(float4 frame, float2 coord, float2 texture_size, float2
video_size, float2 output_size)
{
float lines = fract(coord.y * texture_size.y);
float scale_factor = floor((output_size.y / video_size.y) + 0.4999);
return (scanline_toggle > 0.5 && (lines < (1.0 / scale_factor * THICKNESS)))
? frame * vec4(1.0 - DARKNESS) : frame;
}
float2 interp_coord(float2 coord, float2 texture_size)
{
vec2 p = coord.xy;
p = p * texture_size.xy + vec2(0.5, 0.5);
vec2 i = floor(p);
vec2 f = p - i;
// Smoothstep - amazingly, smoothstep() is slower than calculating directly the expression!
f = f * f * f * f * (f * (f * (-20.0 * f + vec2(70.0, 70.0)) - vec2(84.0, 84.0)) + vec2(35.0, 35.0));
p = i + f;
p = (p - vec2(0.5, 0.5)) * 1.0 / texture_size;
return p;
}
float4 border(float2 texture_size, float2 video_size, float2 output_size,
float frame_count, float2 tex, COMPAT_Texture2D(decal), float2 tex_border, COMPAT_Texture2D(ORIG))
{
float4 effect = COMPAT_Sample(decal, tex_border);
float2 coord = (interp_toggle < 0.5) ? tex : interp_coord(tex, texture_size);
float4 frame = COMPAT_SamplePoint(ORIG, coord);
frame = scanlines(frame, tex, texture_size, video_size, output_size);
if (fragcoord.x < 1.0 && fragcoord.x > 0.0 && fragcoord.y < 1.0 && fragcoord.y > 0.0)
return frame;
else return effect;
}
float4 main_fragment(prev PASSPREV3 : TEXUNIT1, COMPAT_IN_FRAGMENT) : COMPAT_Output
{
return border(COMPAT_texture_size, COMPAT_video_size, COMPAT_output_size,
COMPAT_frame_count, VOUT.texCoord, decal, VOUT.tex_border, PASSPREV_texture(3));
}
COMPAT_END
Here’s a basic preset using that shader and putting 4xbrz in front of it, though you’ll notice that larger initial framebuffers make the blur passes less effective:
shaders = 4
shader0 = ../xbrz/shaders/4xbrz.cg
scale_type0 = source
scale0 = 4.0
filter_linear0 = false
shader1 = ../blurs/blur11fast-horizontal.cg
filter_linear1 = true
scale_type1 = source
shader2 = ../blurs/blur11fast-vertical.cg
filter_linear2 = true
scale_type2 = source
shader3 = resources/bigblur.cg
filter_linear3 = true
parameters = "integer_scale"
integer_scale = 0.0
If the only thing you’re using the image-adjustment shader for is overscan cropping, that can be added to the border shader(s) pretty easily, instead. I’ve already done that with the effect-border-iq slang shader but haven’t added it to the Cg one. As you can see, these particular shaders are sort of in flux at the moment, and I’m trying different things in each one 