mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-23 00:01:31 +11:00
Merge pull request #447 from fishcu/fishcu/update-average-fill-scaling
Update average fill
This commit is contained in:
commit
93dfa33afe
|
@ -10,6 +10,13 @@
|
||||||
This is useful for certain games that do not render a full image to maintain
|
This is useful for certain games that do not render a full image to maintain
|
||||||
the overall aspect ratio and to avoid burn-in.
|
the overall aspect ratio and to avoid burn-in.
|
||||||
|
|
||||||
|
The preset also allows you to extend the original content to a larger
|
||||||
|
screen. It's recommended to set the video scaling options as follows:
|
||||||
|
- Turn integer scaling OFF
|
||||||
|
- Set aspect ratio to FULL
|
||||||
|
The shader will then take over and handle the proper scaling and aspect
|
||||||
|
ratio of the input.
|
||||||
|
|
||||||
In case the image is cropped on multiple sides, different blend modes for
|
In case the image is cropped on multiple sides, different blend modes for
|
||||||
the corner are available. Simply change the parameter for the "corner blend
|
the corner are available. Simply change the parameter for the "corner blend
|
||||||
mode".
|
mode".
|
||||||
|
@ -20,6 +27,7 @@
|
||||||
3 = Smooth angle-based blending
|
3 = Smooth angle-based blending
|
||||||
|
|
||||||
Changelog:
|
Changelog:
|
||||||
|
v1.1: Add extension modes from blur fill; Add average gamma adjustment.
|
||||||
v1.0: Initial release.
|
v1.0: Initial release.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -27,18 +35,26 @@
|
||||||
|
|
||||||
layout(push_constant) uniform Push {
|
layout(push_constant) uniform Push {
|
||||||
vec4 InputSize;
|
vec4 InputSize;
|
||||||
vec4 OriginalSize;
|
vec4 FinalViewportSize;
|
||||||
vec4 OutputSize;
|
|
||||||
uint FrameCount;
|
|
||||||
float OS_CROP_TOP;
|
float OS_CROP_TOP;
|
||||||
float OS_CROP_BOTTOM;
|
float OS_CROP_BOTTOM;
|
||||||
float OS_CROP_LEFT;
|
float OS_CROP_LEFT;
|
||||||
float OS_CROP_RIGHT;
|
float OS_CROP_RIGHT;
|
||||||
float CORNER_BLEND_MODE;
|
float CENTER_CROP;
|
||||||
float SAMPLE_SIZE;
|
float SAMPLE_SIZE;
|
||||||
|
float EXTEND_H;
|
||||||
|
float EXTEND_V;
|
||||||
|
float CORNER_BLEND_MODE;
|
||||||
|
float FORCE_ASPECT_RATIO;
|
||||||
|
float ASPECT_H;
|
||||||
|
float ASPECT_V;
|
||||||
|
float FORCE_INTEGER_SCALING;
|
||||||
|
float FILL_GAMMA;
|
||||||
}
|
}
|
||||||
param;
|
param;
|
||||||
|
|
||||||
|
#include "../blur_fill/scaling.slang"
|
||||||
|
|
||||||
layout(std140, set = 0, binding = 0) uniform UBO { mat4 MVP; }
|
layout(std140, set = 0, binding = 0) uniform UBO { mat4 MVP; }
|
||||||
global;
|
global;
|
||||||
|
|
||||||
|
@ -66,11 +82,11 @@ layout(set = 0, binding = 6) uniform sampler2D Right;
|
||||||
// For mipmap sampling, use a big offset to get the average of a PoT input.
|
// For mipmap sampling, use a big offset to get the average of a PoT input.
|
||||||
#define BIG_NUMBER 9000.1
|
#define BIG_NUMBER 9000.1
|
||||||
|
|
||||||
vec3 blend_corner(vec3 a, // The first color to blend
|
vec3 blend_corner(vec3 a, // The first color to blend
|
||||||
vec3 b, // The second color to blend
|
vec3 b, // The second color to blend
|
||||||
float wa, // The weight of the first color
|
float wa, // The weight of the first color
|
||||||
float wb, // The weight of the second color
|
float wb, // The weight of the second color
|
||||||
vec2 pixel_coord, // The coordinate to evaluate the blend for
|
vec2 coord, // The coordinate to evaluate the blend for
|
||||||
vec2 corner_coord, // The coordinate of the corner of the
|
vec2 corner_coord, // The coordinate of the corner of the
|
||||||
// content after cropping
|
// content after cropping
|
||||||
vec2 gap_size // The component-wise distance from the corner
|
vec2 gap_size // The component-wise distance from the corner
|
||||||
|
@ -89,7 +105,7 @@ vec3 blend_corner(vec3 a, // The first color to blend
|
||||||
case 3:
|
case 3:
|
||||||
default:
|
default:
|
||||||
// Angle blend
|
// Angle blend
|
||||||
const vec2 delta = (pixel_coord - corner_coord) / gap_size;
|
const vec2 delta = (coord - corner_coord) / gap_size;
|
||||||
// Use absolutes to always operate in 1st quadrant.
|
// Use absolutes to always operate in 1st quadrant.
|
||||||
// This makes the angle work out to be correct in all cases when
|
// This makes the angle work out to be correct in all cases when
|
||||||
// carefully choosing argument ordering.
|
// carefully choosing argument ordering.
|
||||||
|
@ -100,90 +116,139 @@ vec3 blend_corner(vec3 a, // The first color to blend
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const vec2 pixel_coord = vTexCoord * param.InputSize.xy;
|
const vec2 pixel_coord = o2i(vTexCoord) * param.InputSize.xy;
|
||||||
if (pixel_coord.x < param.OS_CROP_LEFT) {
|
if (pixel_coord.x < param.OS_CROP_LEFT) {
|
||||||
|
if (param.EXTEND_H < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const vec3 left = textureLod(Left, vec2(0.5), BIG_NUMBER).rgb;
|
const vec3 left = textureLod(Left, vec2(0.5), BIG_NUMBER).rgb;
|
||||||
if (pixel_coord.y < param.OS_CROP_TOP) {
|
if (pixel_coord.y < param.OS_CROP_TOP) {
|
||||||
|
if (param.EXTEND_V < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Top left corner
|
// Top left corner
|
||||||
const vec3 top = textureLod(Top, vec2(0.5), BIG_NUMBER).rgb;
|
const vec3 top = textureLod(Top, vec2(0.5), BIG_NUMBER).rgb;
|
||||||
|
const vec2 content_corner =
|
||||||
|
i2o(vec2(param.OS_CROP_LEFT, param.OS_CROP_TOP) *
|
||||||
|
param.InputSize.zw);
|
||||||
|
const vec2 viewport_corner = vec2(0.0, 0.0);
|
||||||
FragColor =
|
FragColor =
|
||||||
vec4(blend_corner(left, top,
|
vec4(blend_corner(left, top,
|
||||||
param.InputSize.y - param.OS_CROP_TOP -
|
param.InputSize.y - param.OS_CROP_TOP -
|
||||||
param.OS_CROP_BOTTOM,
|
param.OS_CROP_BOTTOM,
|
||||||
param.InputSize.x - param.OS_CROP_LEFT -
|
param.InputSize.x - param.OS_CROP_LEFT -
|
||||||
param.OS_CROP_RIGHT,
|
param.OS_CROP_RIGHT,
|
||||||
pixel_coord,
|
vTexCoord, content_corner,
|
||||||
vec2(param.OS_CROP_LEFT, param.OS_CROP_TOP),
|
viewport_corner - content_corner),
|
||||||
vec2(param.OS_CROP_LEFT, param.OS_CROP_TOP)),
|
|
||||||
1.0);
|
1.0);
|
||||||
|
FragColor.rgb = pow(FragColor.rgb, vec3(param.FILL_GAMMA));
|
||||||
} else if (pixel_coord.y < param.InputSize.y - param.OS_CROP_BOTTOM) {
|
} else if (pixel_coord.y < param.InputSize.y - param.OS_CROP_BOTTOM) {
|
||||||
// Left bar
|
// Left bar
|
||||||
FragColor = vec4(left, 1.0);
|
FragColor = vec4(pow(left, vec3(param.FILL_GAMMA)), 1.0);
|
||||||
} else {
|
} else {
|
||||||
|
if (param.EXTEND_V < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Bottom left corner
|
// Bottom left corner
|
||||||
const vec3 bottom = textureLod(Bottom, vec2(0.5), BIG_NUMBER).rgb;
|
const vec3 bottom = textureLod(Bottom, vec2(0.5), BIG_NUMBER).rgb;
|
||||||
FragColor = vec4(
|
const vec2 content_corner =
|
||||||
blend_corner(left, bottom,
|
i2o(vec2(param.OS_CROP_LEFT,
|
||||||
param.InputSize.y - param.OS_CROP_TOP -
|
param.InputSize.y - param.OS_CROP_BOTTOM) *
|
||||||
param.OS_CROP_BOTTOM,
|
param.InputSize.zw);
|
||||||
param.InputSize.x - param.OS_CROP_LEFT -
|
const vec2 viewport_corner = vec2(0.0, 1.0);
|
||||||
param.OS_CROP_RIGHT,
|
FragColor =
|
||||||
pixel_coord,
|
vec4(blend_corner(left, bottom,
|
||||||
vec2(param.OS_CROP_LEFT,
|
param.InputSize.y - param.OS_CROP_TOP -
|
||||||
param.InputSize.y - param.OS_CROP_BOTTOM),
|
param.OS_CROP_BOTTOM,
|
||||||
vec2(param.OS_CROP_LEFT, param.OS_CROP_BOTTOM)),
|
param.InputSize.x - param.OS_CROP_LEFT -
|
||||||
1.0);
|
param.OS_CROP_RIGHT,
|
||||||
|
vTexCoord, content_corner,
|
||||||
|
viewport_corner - content_corner),
|
||||||
|
1.0);
|
||||||
|
FragColor.rgb = pow(FragColor.rgb, vec3(param.FILL_GAMMA));
|
||||||
}
|
}
|
||||||
} else if (pixel_coord.x < param.InputSize.x - param.OS_CROP_RIGHT) {
|
} else if (pixel_coord.x < param.InputSize.x - param.OS_CROP_RIGHT) {
|
||||||
if (pixel_coord.y < param.OS_CROP_TOP) {
|
if (pixel_coord.y < param.OS_CROP_TOP) {
|
||||||
|
if (param.EXTEND_V < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Top bar
|
// Top bar
|
||||||
FragColor = vec4(textureLod(Top, vec2(0.5), BIG_NUMBER).rgb, 1.0);
|
FragColor = vec4(textureLod(Top, vec2(0.5), BIG_NUMBER).rgb, 1.0);
|
||||||
|
FragColor.rgb = pow(FragColor.rgb, vec3(param.FILL_GAMMA));
|
||||||
} else if (pixel_coord.y < param.InputSize.y - param.OS_CROP_BOTTOM) {
|
} else if (pixel_coord.y < param.InputSize.y - param.OS_CROP_BOTTOM) {
|
||||||
// Uncropped
|
// Uncropped
|
||||||
// Do a sharp (nearest neighbor) resampling.
|
// Do a sharp (nearest neighbor) resampling.
|
||||||
FragColor = vec4(
|
FragColor = vec4(
|
||||||
texture(Input, (floor(vTexCoord * param.InputSize.xy) + 0.5) *
|
texture(Input, (floor(pixel_coord) + 0.5) * param.InputSize.zw)
|
||||||
param.InputSize.zw)
|
|
||||||
.rgb,
|
.rgb,
|
||||||
1.0);
|
1.0);
|
||||||
} else {
|
} else {
|
||||||
|
if (param.EXTEND_V < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Bottom bar
|
// Bottom bar
|
||||||
FragColor =
|
FragColor =
|
||||||
vec4(textureLod(Bottom, vec2(0.5), BIG_NUMBER).rgb, 1.0);
|
vec4(textureLod(Bottom, vec2(0.5), BIG_NUMBER).rgb, 1.0);
|
||||||
|
FragColor.rgb = pow(FragColor.rgb, vec3(param.FILL_GAMMA));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (param.EXTEND_H < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const vec3 right = textureLod(Right, vec2(0.5), BIG_NUMBER).rgb;
|
const vec3 right = textureLod(Right, vec2(0.5), BIG_NUMBER).rgb;
|
||||||
if (pixel_coord.y < param.OS_CROP_TOP) {
|
if (pixel_coord.y < param.OS_CROP_TOP) {
|
||||||
|
if (param.EXTEND_V < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Top right corner
|
// Top right corner
|
||||||
const vec3 top = textureLod(Top, vec2(0.5), BIG_NUMBER).rgb;
|
const vec3 top = textureLod(Top, vec2(0.5), BIG_NUMBER).rgb;
|
||||||
|
const vec2 content_corner =
|
||||||
|
i2o(vec2(param.InputSize.x - param.OS_CROP_RIGHT,
|
||||||
|
param.OS_CROP_TOP) *
|
||||||
|
param.InputSize.zw);
|
||||||
|
const vec2 viewport_corner = vec2(1.0, 0.0);
|
||||||
FragColor =
|
FragColor =
|
||||||
vec4(blend_corner(right, top,
|
vec4(blend_corner(right, top,
|
||||||
param.InputSize.y - param.OS_CROP_TOP -
|
param.InputSize.y - param.OS_CROP_TOP -
|
||||||
param.OS_CROP_BOTTOM,
|
param.OS_CROP_BOTTOM,
|
||||||
param.InputSize.x - param.OS_CROP_LEFT -
|
param.InputSize.x - param.OS_CROP_LEFT -
|
||||||
param.OS_CROP_RIGHT,
|
param.OS_CROP_RIGHT,
|
||||||
pixel_coord,
|
vTexCoord, content_corner,
|
||||||
vec2(param.InputSize.x - param.OS_CROP_RIGHT,
|
viewport_corner - content_corner),
|
||||||
param.OS_CROP_TOP),
|
|
||||||
vec2(param.OS_CROP_RIGHT, param.OS_CROP_TOP)),
|
|
||||||
1.0);
|
1.0);
|
||||||
|
FragColor.rgb = pow(FragColor.rgb, vec3(param.FILL_GAMMA));
|
||||||
} else if (pixel_coord.y < param.InputSize.y - param.OS_CROP_BOTTOM) {
|
} else if (pixel_coord.y < param.InputSize.y - param.OS_CROP_BOTTOM) {
|
||||||
// Right bar
|
// Right bar
|
||||||
FragColor = vec4(right, 1.0);
|
FragColor = vec4(pow(right, vec3(param.FILL_GAMMA)), 1.0);
|
||||||
} else {
|
} else {
|
||||||
|
if (param.EXTEND_V < 0.5) {
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Bottom right corner
|
// Bottom right corner
|
||||||
const vec3 bottom = textureLod(Bottom, vec2(0.5), BIG_NUMBER).rgb;
|
const vec3 bottom = textureLod(Bottom, vec2(0.5), BIG_NUMBER).rgb;
|
||||||
FragColor = vec4(
|
const vec2 content_corner =
|
||||||
blend_corner(right, bottom,
|
i2o(vec2(param.InputSize.x - param.OS_CROP_RIGHT,
|
||||||
param.InputSize.y - param.OS_CROP_TOP -
|
param.InputSize.y - param.OS_CROP_BOTTOM) *
|
||||||
param.OS_CROP_BOTTOM,
|
param.InputSize.zw);
|
||||||
param.InputSize.x - param.OS_CROP_LEFT -
|
const vec2 viewport_corner = vec2(1.0, 1.0);
|
||||||
param.OS_CROP_RIGHT,
|
FragColor =
|
||||||
pixel_coord,
|
vec4(blend_corner(right, bottom,
|
||||||
vec2(param.InputSize.x - param.OS_CROP_RIGHT,
|
param.InputSize.y - param.OS_CROP_TOP -
|
||||||
param.InputSize.y - param.OS_CROP_BOTTOM),
|
param.OS_CROP_BOTTOM,
|
||||||
vec2(param.OS_CROP_RIGHT, param.OS_CROP_BOTTOM)),
|
param.InputSize.x - param.OS_CROP_LEFT -
|
||||||
1.0);
|
param.OS_CROP_RIGHT,
|
||||||
|
vTexCoord, content_corner,
|
||||||
|
viewport_corner - content_corner),
|
||||||
|
1.0);
|
||||||
|
FragColor.rgb = pow(FragColor.rgb, vec3(param.FILL_GAMMA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,25 @@
|
||||||
// See compose.slang for copyright and other information.
|
// See compose.slang for copyright and other information.
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#pragma parameter AVERAGE_FILL_SETTINGS "=== Average fill v1.0 settings ===" 0.0 0.0 1.0 1.0
|
#pragma parameter AVERAGE_FILL_SETTINGS "=== Average fill v1.1 settings ===" 0.0 0.0 1.0 1.0
|
||||||
#pragma parameter OS_CROP_TOP "Overscan crop top" 16.0 0.0 1024.0 1.0
|
#pragma parameter OS_CROP_TOP "Overscan crop top" 8.0 0.0 1024.0 1.0
|
||||||
#pragma parameter OS_CROP_BOTTOM "Overscan crop bottom" 16.0 0.0 1024.0 1.0
|
#pragma parameter OS_CROP_BOTTOM "Overscan crop bottom" 8.0 0.0 1024.0 1.0
|
||||||
#pragma parameter OS_CROP_LEFT "Overscan crop left" 0.0 0.0 1024.0 1.0
|
#pragma parameter OS_CROP_LEFT "Overscan crop left" 0.0 0.0 1024.0 1.0
|
||||||
#pragma parameter OS_CROP_RIGHT "Overscan crop right" 0.0 0.0 1024.0 1.0
|
#pragma parameter OS_CROP_RIGHT "Overscan crop right" 0.0 0.0 1024.0 1.0
|
||||||
#pragma parameter CORNER_BLEND_MODE "Cropped corner blend mode" 0.0 0.0 3.0 1.0
|
|
||||||
|
#pragma parameter CENTER_CROP "Center cropped area" 1.0 0.0 1.0 1.0
|
||||||
|
|
||||||
#pragma parameter SAMPLE_SIZE "No. of lines for calculating the average" 4.0 1.0 64.0 1.0
|
#pragma parameter SAMPLE_SIZE "No. of lines for calculating the average" 4.0 1.0 64.0 1.0
|
||||||
|
|
||||||
|
#pragma parameter EXTEND_H "Extend the fill horizontally" 1.0 0.0 1.0 1.0
|
||||||
|
#pragma parameter EXTEND_V "Extend the fill vertically" 1.0 0.0 1.0 1.0
|
||||||
|
|
||||||
|
#pragma parameter CORNER_BLEND_MODE "Cropped corner blend mode" 0.0 0.0 3.0 1.0
|
||||||
|
|
||||||
|
#pragma parameter FORCE_ASPECT_RATIO "Force aspect ratio" 0.0 0.0 1.0 1.0
|
||||||
|
#pragma parameter ASPECT_H "Horizontal aspect ratio before crop" 4.0 1.0 100.0 1.0
|
||||||
|
#pragma parameter ASPECT_V "Vertical aspect ratio before crop" 3.0 1.0 100.0 1.0
|
||||||
|
#pragma parameter FORCE_INTEGER_SCALING "Force integer scaling" 1.0 0.0 1.0 1.0
|
||||||
|
|
||||||
|
#pragma parameter FILL_GAMMA "Background fill gamma adjustment" 1.0 0.5 2.0 0.1
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include "parameters.slang"
|
|
||||||
|
|
||||||
// See compose.slang for copyright and other information.
|
// See compose.slang for copyright and other information.
|
||||||
|
|
||||||
// Pixels in input coord. space
|
// Pixels in input coord. space
|
||||||
|
@ -48,17 +46,24 @@ vec2 scale_o2i() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In unit space (output to input)
|
// Input to output scaling, in unit coordinate systems.
|
||||||
|
vec2 scale_i2o() { return 1.0 / scale_o2i(); }
|
||||||
|
|
||||||
|
// Get adjusted center in input unit coordinate system.
|
||||||
|
vec2 get_input_center() {
|
||||||
|
return param.CENTER_CROP > 0.5
|
||||||
|
? 0.5 * param.InputSize.zw *
|
||||||
|
vec2(param.OS_CROP_LEFT + param.InputSize.x -
|
||||||
|
param.OS_CROP_RIGHT,
|
||||||
|
param.OS_CROP_TOP + param.InputSize.y -
|
||||||
|
param.OS_CROP_BOTTOM)
|
||||||
|
: vec2(0.49999);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In unit space (output to input).
|
||||||
// coord_in_input_space = o2i(coord_in_output_space)
|
// coord_in_input_space = o2i(coord_in_output_space)
|
||||||
// This is used to sample from the input texture in the output pass.
|
// This is used to sample from the input texture in the output pass.
|
||||||
vec2 o2i(vec2 x) {
|
vec2 o2i(vec2 x) { return (x - 0.49999) * scale_o2i() + get_input_center(); }
|
||||||
const vec2 center_in =
|
|
||||||
param.CENTER_CROP > 0.5
|
// In unit coordinate systems.
|
||||||
? 0.5 * param.InputSize.zw *
|
vec2 i2o(vec2 x) { return (x - get_input_center()) * scale_i2o() + 0.49999; }
|
||||||
vec2(param.OS_CROP_LEFT + param.InputSize.x -
|
|
||||||
param.OS_CROP_RIGHT,
|
|
||||||
param.OS_CROP_TOP + param.InputSize.y -
|
|
||||||
param.OS_CROP_BOTTOM)
|
|
||||||
: vec2(0.49999);
|
|
||||||
return (x - 0.49999) * scale_o2i() + center_in;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue