├── A-pack ├── A-pack.md ├── Shaders │ ├── bDim-35.hlsl │ ├── bExposure.08.hlsl │ ├── bLift.hlsl │ ├── bShadows-08.hlsl │ ├── bShadows.hlsl │ ├── brighten 20.hlsl │ ├── brighten-10.hlsl │ ├── brightenD.06.hlsl │ ├── bw.hlsl │ ├── bw_luma.hlsl │ ├── contrast.10.hlsl │ ├── dSat.hlsl │ ├── deContrast.hlsl │ ├── expand10_240.hlsl │ ├── exposure.08.hlsl │ ├── sCurve.hlsl │ ├── tooBright.hlsl │ ├── tooDark.12.hlsl │ ├── tooDark.24.hlsl │ ├── tooDark.hlsl │ ├── vibrance-15.hlsl │ └── vibrance.35.hlsl ├── Shaders11 │ ├── bDim-35.hlsl │ ├── bLift.hlsl │ ├── bShadows-08.hlsl │ ├── brighten 20.hlsl │ ├── bw.hlsl │ ├── bw_luma.hlsl │ ├── contrast.10.hlsl │ ├── dSat.hlsl │ ├── deContrast.hlsl │ ├── expand10_240.hlsl │ ├── exposure.08.hlsl │ ├── sCurve.hlsl │ ├── tooBright.hlsl │ ├── tooDark-30.hlsl │ ├── tooDark.24.hlsl │ ├── vibrance-15.hlsl │ └── vibrance.35.hlsl ├── mpv │ ├── bDim-35.hook │ ├── bLift.hook │ ├── bShadows-08.hk │ ├── bw.hk │ ├── bw_noChroma.hk │ ├── contrast.10.hk │ ├── dSat.hk │ ├── deContrast.glsl │ ├── expand10_240.hk │ ├── exposure.08.hk │ ├── portable_config │ │ ├── input.conf │ │ └── scripts │ │ │ └── switch-shaders.js │ ├── sCurve.hk.glsl │ ├── tooBright.hk │ ├── tooDark.12.hk │ ├── tooDark.24.hk │ ├── vibrance-15.hook │ └── vibrance.35.hk └── readme.md ├── Effects ├── CrossHatch.hook.glsl ├── Sepia.md ├── bCrossHatch.hlsl ├── bStipple.hlsl ├── dots.hook.glsl └── gr-Dots.hlsl ├── FilmGrain_Noise ├── FilmGrain1.hlsl ├── Readme_FilmGrain.md ├── SweetFx.FilmGrain.hlsl ├── bNoise.hlsl ├── blank_color_ffmpeg_1080p_Gray128_10s.mp4 ├── blank_color_ffmpeg_1080p_Gray128_rgb24_snapshot_00.05_[2020.10.19_20.57.46].png ├── dx11 │ └── grain.hlsl ├── grain-profile_parabola_linear_uniform.png ├── grain.35_D1vs.30.png ├── grain.hlsl ├── grain_densityCurve-vsLuma_D0-black_D1-red.png └── mpv │ ├── grain.glsl │ └── grain_luma.glsl ├── MPC-HC_Shaders-Menu.jpg ├── README.md ├── assets ├── Pixelate1_100_1080p.png ├── Posterize.vs.Posterize2_8-b.png ├── Sobel_Sat_Color_x1280.jpg ├── Y_map4.jpg ├── bHatch_6levels_4col_pop_x1280.png ├── bPosterize2-4_rgb_x1280.jpg ├── img │ ├── ColorBarsHD720_Colormatrix.png │ ├── ColorBarsHD720_Sepia_Paint-4.png │ ├── ColorBarsHD720_noChroma.png │ ├── ColorBarsHD720_rgb-nTint.png │ ├── adm-bSegments.png │ ├── mp-hc_HideWindowedControls.jpg │ ├── mpc-be_minimal_flybar_seekbar.jpg │ ├── mpc-hc_O_Keys_Shader.png │ ├── mpvnet_menu.jpg │ └── scr_A-Pack v1.40 - video Adjustments shaders.jpg ├── mpv_LSobel.inv.dk.jpg ├── mpv_bStipple_x1280.jpg ├── mpv_freichen_x1280_grey.png ├── mpv_invSobel_Luma_noThreshold.jpg ├── original_exterior_49.05_x1280.png ├── pencil-sketch_EdgeSharpen_x1280_grey.png ├── rgb_luma-map4_0.25color.jpg └── vlc_gradient-edge-cartoon_720p.png ├── bPixelate.hlsl ├── bStrobe.hlsl ├── barMask.hlsl ├── blur ├── bSmooth.hlsl ├── blurGauss.hook.glsl ├── blurGaussR.hook.glsl ├── blurGauss_pass1.hlsl ├── blurGauss_pass2.hlsl ├── fill_bb.avs └── gSmooth.hook.glsl ├── blurDKawase14.hlsl ├── blurDKawase34.hlsl ├── blurKawase_15.hlsl ├── bw.hlsl ├── edge ├── Sobel_Edge.hook.glsl ├── bCartoonize.avs ├── bSobel_Edge.hlsl └── sharpen │ ├── dx9 │ ├── sharpen.hlsl │ └── unsharp.hlsl │ └── readme.md ├── img ├── Contrast.14_vs_ContrastBW.png ├── Curves_basics.png ├── Exposure_vs_Brightness10-10.png ├── Lift_vs_Brightness_0.1-0.1.png ├── S-curve.png ├── Shadows-15_vs_Lift_Brightness-10.png ├── TooDark-30_vs_bGamma.15.png ├── bShadows-0.10_8vs4.png ├── brightenD.png ├── brightness_increase_methods.png ├── contrast_vs_sCurves.png ├── deContrast.png ├── deContrast_vs_contrast.png ├── hsplit_scr_Edge_Detect_1080p.jpg ├── mpc-hc_Debug_Shaders.png ├── mpc-hc_Select_Shaders_Menu.png ├── scr_syntaxic_coloring_npp.png ├── tooDark.24_vs_BrigtenD.06.png └── tooDark_contrast.png ├── mpv ├── Ex_texture.hook.glsl ├── NoChroma.hook ├── bSat.hook.glsl ├── bShadows_next.hook ├── bSide.hook.glsl ├── bw.hook.glsl ├── cs_wkgroups.hook.glsl ├── lut │ ├── Readme.md │ ├── bw-4.hook.glsl │ ├── clut_id4.hook │ ├── hald-2-identity_8x8_cube4.png │ ├── hald-2-identity_8x8_cube4.ppm │ ├── id-4.cube │ ├── id-9.png │ ├── kodachrome-9.hook.glsl │ └── sepia_paint-4.hook.glsl ├── portable_config │ ├── mpv.conf │ └── script-opts │ │ └── btime.conf ├── scr │ ├── mpv-menu-plugin_v2.1_btime.png │ └── mpv-menu_jump_seek.png ├── scr_mpv_avg-bitrate.jpg ├── settings │ └── scripts │ │ ├── avg-bitrate.js │ │ ├── bstat.js │ │ ├── btime.js │ │ ├── btime_osd-bar.jpg │ │ ├── countdown.lua │ │ ├── error-osd.lua │ │ ├── menu_window_scale.lua │ │ ├── mpv-menu_dynamic_win10-dark.png │ │ ├── mpv-menu_win10-light-1440p-hidpi125_pause-indicator.png │ │ ├── obs_countdown.js │ │ ├── overlay0.js │ │ ├── restart-mpv.js │ │ ├── scr_mpv_show-shaders.jpg │ │ ├── seek-bar.jpg │ │ ├── store-shaders.js │ │ └── switch-shader.js └── vibrance_next.hk ├── test_LimitedRange ├── Avidemux │ └── Settings │ │ └── Custom │ │ ├── Readme.md │ │ ├── _ix.py │ │ ├── _ixxx.py │ │ ├── adm-vThumb_UI.png │ │ ├── bSegments.py │ │ ├── black_A-B.py │ │ └── saveFull.py ├── ColorBarsHD_720p.mp4 ├── ColorBarsHD_full_avs720p.jpg ├── LumaHistogram.avs ├── Readme.md ├── avs_pc.709_720p-001.png ├── avs_rec709_720p-full.png ├── bHighL.hlsl ├── bInsert.py ├── bSplit.py ├── dirLoad.py ├── ex_luma.csv ├── ffm4b.bat ├── gen_ColorBarsHD.avs ├── graycard9_0-32-64-96-128-159-191-223-255.bmp ├── graycard9_1392x336p30-15s_0-32-64-96-128-159-191-223-255.mp4 ├── luma_stats.avs └── test_version.avs ├── test_linearSampling ├── Offset 0.5 Sampling artefact_zoomed.png ├── Test_HW_Linear_Sampling.hook ├── bSmooth_test.hlsl ├── bw_test_motif_1080p_15s.mp4 ├── bw_test_motif_720p_rgb32.png ├── expected_result_mpv.png ├── test_linearSampling1_motif.hlsl └── test_linearSampling2_result.hlsl └── test_resize ├── pattern1_bw1080x1080.png ├── pattern1_bw18.png └── pattern1_bw180x180.png /A-pack/Shaders/bDim-35.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Exposure -0.35 3 | 4 | /* --- bDim (dx9), bExposure --- */ 5 | /* v1.40 (11/2023) released by butterw under GPLv3 6 | (1 texture, 1 arithmetic) 7 | 8 | Exposure: Dims or lights-up the video. 9 | 10 | c0 = c0 *(1.0+Exposure) = c0 + c0*Exposure 11 | with c0: pixel.rgb in [0, 1.0]. 12 | 13 | - Parameter Exposure, typ: [-0.8 to 1], 0: no effect. 14 | [-1, ..] -1: All black. 15 | negative: dims, ex: -0.35 16 | with strong values (ex: -0.8) can be used for a night-for-day effect (make a day-shot look like a night shot). 17 | positive: lights-up. 18 | ex: 1.0 will blow-up White for a kind of vintage effect. 19 | */ 20 | sampler s0: register(s0); 21 | 22 | float4 main(float2 tex: TEXCOORD0): COLOR { 23 | float4 c0 = tex2D(s0, tex); 24 | 25 | c0.rgb = c0 *(1.0 + Exposure); 26 | return c0; 27 | } 28 | -------------------------------------------------------------------------------- /A-pack/Shaders/bExposure.08.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Exposure 0.08 3 | 4 | /* --- bExposure (dx9) --- */ 5 | /* v1.40 (07/2023) released by butterw under GPLv3 6 | /* (1 texture, 1 arithmetic) 7 | 8 | Exposure increases (or decreases) contrast/brightness. 9 | 10 | out = x * (1 + Exposure) = x + x*Exposure 11 | with x, out: pixel.rgb in [0, 1.0] 12 | 13 | Exposure doesn't affect the black point (0, 0). 14 | - Contrast: 1+Exposure. 15 | - Brightness change: Exposure*x. Max at the white point. 16 | 17 | - parameter Exposure, [-1.0, ..], 0: no change, -1: all black 18 | >> Positive: increases contrast/brightness, ex: 0.08 19 | ! input> 1/(1+Exposure) will be clipped. 20 | 21 | negative: decreases contrast/brightness (dims), output<= 1+Exposure. 22 | 23 | */ 24 | sampler s0: register(s0); 25 | 26 | float4 main(float2 tex: TEXCOORD0): COLOR { 27 | float4 c0 = tex2D(s0, tex); 28 | 29 | c0.rgb = c0.rgb *(1.0 + Exposure); 30 | return c0; 31 | } -------------------------------------------------------------------------------- /A-pack/Shaders/bLift.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Lift 0.05 3 | 4 | /* --- bLift (dx9) --- */ 5 | /* v1.01 (2023-06) released by butterw under GPLv3 6 | 7 | c0 = c0*(1 -0.5*Lift) +0.5*Lift = c0 +0.5*Lift*(1-c0) 8 | with c0: pixel.rgb in [0, 1.0] 9 | 10 | - Parameter rgb Lift, 0: no change 11 | negative: darkens the image 12 | positive: lightens the image, ex: 0.05 13 | 14 | Lift limits image crushing 15 | vs. a brightness adjustment (rgb shift): c0 = c0 + Brightness 16 | */ 17 | sampler s0: register(s0); 18 | 19 | float4 main(float2 tex: TEXCOORD0): COLOR { 20 | float4 c0 = tex2D(s0, tex); 21 | 22 | return c0*(1 -0.5*Lift) +0.5*Lift; 23 | } 24 | -------------------------------------------------------------------------------- /A-pack/Shaders/bShadows-08.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Shadows -0.08 3 | 4 | /* --- bShadows (dx9) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 5 arithmetic) 7 | 8 | Darken (or lighten) the shadows. 9 | 10 | out = x + Shadows*(1-x)^4 11 | with x, out: pixel.rgb in [0, 1.0]. 12 | 13 | - parameter Shadows [-1, 1.0], 0: no change 14 | >> Negative: darkens the shadows, ex: -0.10 15 | Use to ensure shadows are darks, doesn't alter the rest of the picture. 16 | Can be used to correct raised black levels. 17 | for Shadows:-0.10, clipped input <0.0736, first order approximation: clips > Negative: darkens the shadows, ex: -0.10 15 | Use to ensure shadows are darks, doesn't alter the rest of the picture. 16 | Can be used to correct raised black levels. 17 | for Shadows:-0.10, clipped input <0.0736, first order approximation: clips > positive: increases brightness without raising the black point. 15 | Contrast is increased in Shadows, but otherwise remains unchanged. 16 | ! clips input >1-Brightness. 17 | 18 | negative: decreases brightness without clipping Shadows. 19 | output <= 1+Brightness. 20 | Contrast is decreased in Shadows, but otherwise remains unchanged. 21 | 22 | */ 23 | sampler s0: register(s0); 24 | 25 | float4 main(float2 tex: TEXCOORD0): COLOR { 26 | float4 c0 = tex2D(s0, tex); 27 | float4 shadowsBleed = 1.0-c0; 28 | shadowsBleed*= shadowsBleed; 29 | shadowsBleed*= shadowsBleed; 30 | shadowsBleed = -Brightness*shadowsBleed +Brightness; 31 | return c0 + shadowsBleed; 32 | } -------------------------------------------------------------------------------- /A-pack/Shaders/bw.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define CoefMonochrome float4(0.18, 0.41, 0.41, 0) //Agfa 200X 3 | 4 | /* --- bw (dx9) --- black&white */ 5 | /* v1.40 (2023-07), released by butterw under GPLv3 6 | (1 texture, 1 arithmetic) 7 | 8 | Transforms a video to black&white using a custom rgba to grayscale conversion coef (CoefMonochrome). 9 | The latter can be changed to achieve a different look. 10 | 11 | -- Grayscale Conversion Coefs -- 12 | float4(1/3., 1/3., 1/3., 0) //Equal weight 13 | float4(0.299, 0.587, 0.114, 0) // mpc-hc Grayscale 14 | float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV: CoefLuma used by bw_luma shader 15 | 16 | Some values for black&white film from SweetFx.Monochrome by CeeJay.dk: 17 | float4(0.18, 0.41, 0.41, 0) //Agfa 200X (default) 18 | float4(0.25, 0.39, 0.36, 0) //Agfapan 25 19 | float4(0.21, 0.40, 0.39, 0) //Agfapan 100 20 | float4(0.20, 0.41, 0.39, 0) //Agfapan 400 21 | float4(0.21, 0.42, 0.37, 0) //Ilford Delta 100 22 | float4(0.22, 0.42, 0.36, 0) //Ilford Delta 400 23 | float4(0.31, 0.36, 0.33, 0) //Ilford Delta 400 Pro & 3200 24 | float4(0.28, 0.41, 0.31, 0) //Ilford FP4 25 | float4(0.23, 0.37, 0.40, 0) //Ilford HP5 26 | float4(0.33, 0.36, 0.31, 0) //Ilford Pan F 27 | float4(0.36, 0.31, 0.33, 0) //Ilford SFX 28 | float4(0.21, 0.42, 0.37, 0) //Ilford XP2 Super 29 | float4(0.24, 0.37, 0.39, 0) //Kodak Tmax 100 30 | float4(0.27, 0.36, 0.37, 0) //Kodak Tmax 400 31 | float4(0.25, 0.35, 0.40, 0) //Kodak Tri-X 32 | */ 33 | 34 | sampler s0: register(s0); 35 | 36 | float4 main(float2 tex: TEXCOORD0): COLOR { 37 | float4 c0 = tex2D(s0, tex); 38 | 39 | return dot(c0, CoefMonochrome); 40 | } -------------------------------------------------------------------------------- /A-pack/Shaders/bw_luma.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | 3 | /* --- bw_luma (dx9) --- */ 4 | /* v1.40 (07/2023) released by butterw under GPLv3 5 | 6 | Displays the grayscale luminance (HDTV luma) image derived from rgb. 7 | Same as the Grayscale shader included with mpc-be (different from the one in mpc-hc). 8 | 9 | */ 10 | sampler s0: register(s0); 11 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 12 | 13 | float4 main(float2 tex: TEXCOORD0): COLOR { 14 | float4 c0 = tex2D(s0, tex); 15 | 16 | return dot(c0, CoefLuma); 17 | } -------------------------------------------------------------------------------- /A-pack/Shaders/contrast.10.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Contrast 0.10 3 | 4 | /* --- contrast (dx9) --- */ 5 | /* v1.40 (07/2023) released by butterw under GPLv3 6 | (1 texture, 1 arithmetic) 7 | 8 | Increases (or decreases) contrast by symmetrical expansion of the rgb histogram around the mid-point (0.5, 0.5). 9 | For asymmetrical expansion use the shader expandB_W (bk, wh) instead. 10 | 11 | out = x + Contrast*(x-0.5) = (1+Contrast)*x -0.5*Contrast 12 | with x, out: pixel.rgb in [0, 1.0] 13 | 14 | Mid-point is unaffected by contrast. 15 | contrast, d/dx: 1+Contrast 16 | brightness change: Contrast*(x-0.5) 17 | 18 | parameter Contrast, [-1.0, ..], 0: no effect, -1: All mid-gray (0.5) 19 | >> Positive: increases the contrast, ex: 0.10 20 | brightness is increased above the mid-point, and decreased below the mid-point. 21 | ! input will be clipped: 22 | < Contrast/2. *1/(1+Contrast) 23 | > 1-Contrast/2. *1/(1+Contrast) 24 | for Contrast 0.10: clips <0.0455 and >0.954 25 | 26 | negative: decreases the contrast. 27 | 28 | */ 29 | sampler s0: register(s0); 30 | 31 | 32 | float4 main(float2 tex: TEXCOORD0): COLOR { 33 | float4 c0 = tex2D(s0, tex); 34 | 35 | c0.rgb = c0.rgb*(1 +Contrast) -0.5*Contrast; 36 | return c0; 37 | } -------------------------------------------------------------------------------- /A-pack/Shaders/dSat.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define SatFactor -0.25 3 | 4 | /* --- dSat (dx9) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 3 arithmetic) 7 | 8 | A lightweight desaturation shader with a touch of red exposure to avoid pasty grey skintones. 9 | faster than vibrance-15. 10 | 11 | param SatFactor [-1, ..], 0: no Effect, -1: Gray 12 | negative: desaturation, ex:-0.25 13 | 14 | */ 15 | #define rExposure float3(0.05, 0.008, 0) 16 | #define LumaCoef float4(0.2126, 0.7152, 0.0722, 0) 17 | 18 | sampler s0: register(s0); 19 | 20 | float4 main(float2 tex: TEXCOORD0): COLOR { 21 | float4 c0 = tex2D(s0, tex); 22 | 23 | float gray = dot(c0, LumaCoef); 24 | c0 = lerp(gray, c0, 1.0 + SatFactor); 25 | c0.rgb = c0.rgb *(1.0 + rExposure); 26 | return c0; 27 | } -------------------------------------------------------------------------------- /A-pack/Shaders/deContrast.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define S -0.07 3 | #define n 4 4 | 5 | /* --- deContrast (dx9) --- */ 6 | 7 | /* v1.50 (2023-11) released by butterw under GPLv3 8 | (with S<0, ex: -0.07) Reduces midtone contrast. Also boosts contrast in shadows/highlights. 9 | n:4 (1 texture, 6 arithmetic). 10 | 11 | # Sn brightness/contrast curve 12 | out = f(x, S) = x + S/2*(2*x-1) *(1-(2*x-1)^n) = x + S/2*x1 *(1-x1^n) 13 | with n even >0 (ex: 4, 6, 8, 16, etc.) 14 | and x1 = 2*x -1 15 | and x, out pixel.rgb in [0, 1.0]. 16 | 17 | # Brightness 18 | f(x:0)=0; f(0.5)=0.5; f(1)=1. 19 | S<0: brightness is increased below the midpoint (x: 0.5) and decreased above the midpoint. 20 | 21 | # Contrast 22 | - contrast(x:0.5): 1+S 23 | - contrast(x:0)=contrast(x:1): 1-S*n 24 | 25 | 26 | Parameter S [-0.15, 0.15], 0: no effect 27 | - S>0: This symmetrical S-curve is a smoothed version of the contrast/levels linear curve. It provide a constant contrast increase (S) for a wide midtone range (with n=4+), and while it doesn't clip, contrast is decreased (up to S*n) in the highlights/shadows region. Because of this the sigmoid (sCurve shader) is probably a better choice for increasing contrast. 28 | - S<0: inverse S-curve. Now contrast is decreased by a constant value (S) in a wide midtone range and contrast is increased in the Shadows/Highlights (by |S|*n at x=0 and x=1). 29 | The plot https://github.com/butterw/bShaders/blob/master/img/deContrast_vs_contrast.png compares the contrast for different adjustment methods. This shader can be used to correct over-contrasted videos to get a more natural looking result. It's also good for restoring contrast/improving brightness in dark or bright videos. 30 | 31 | Parameter n, even integer [4: default, 8, 16, 6, ..] 32 | The higher n is, the wider the midtone contrast decrease range (with S<0) but also the stronger the contrast increase in highlights/shadows. 33 | n:8 (1 texture, 7 arithmetic) 34 | n:4 (1 texture, 6 arithmetic), default 35 | n:2 (1 texture, 5 arithmetic), S3(S/2) Hermite smoothstep interpolation. no flat midtone contrast decrease range. 36 | */ 37 | sampler s0: register(s0); 38 | 39 | float4 main(float2 tex: TEXCOORD0): COLOR { 40 | float4 c0 = tex2D(s0, tex); 41 | 42 | float3 c1 = 2*c0.rgb -1; 43 | c0.rgb+= 0.5*S *c1 *( 1.0 -pow(c1, n) ); 44 | return c0; 45 | } -------------------------------------------------------------------------------- /A-pack/Shaders/expand10_240.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define bk 10 3 | #define wh 240 4 | 5 | /* --- expandB_W (dx9) xB_W --- */ 6 | /* v1.40 (07/2023) released by butterw under GPLv3 7 | (1 texture, 1 arithmetic) 8 | 9 | Expands the rgb histogram by applying the levels curve, increasing the contrast. 10 | Can be useful to lift the haze on lackluster internet videos. 11 | 12 | ! Parameter values (bk, wh) use rgb8 color scale [0, 255.0], not [0, 1.0]. 13 | bk: new Black point, wh: new White point, (bk:0, wh:255): no effect 14 | ! Any input below bk, or above wh will be clipped. 15 | 16 | Modified version of the MPC-HC shader "16-235 to 0-255.hlsl". 17 | allows custom values instead of (16, 235) for the new rgb Black/White points 18 | ex: (bk: 10, wh: 240), contrast=1.109 19 | The 2 parameters allow for asymmetrical expansion (bk!= 255-wh) which is not available with the (single parameter) constrast shader. 20 | 21 | Levels curve is a linear equation: 22 | out = (x -const_1) *contrast = x*contrast -const_1*contrast 23 | with contrast = 255.0/(wh-bk) 24 | and x, out: input, output pixel.rgb in [0, 1.0]. 25 | out = (x*255. -bk) /(wh-bk) 26 | 27 | */ 28 | sampler s0: register(s0); 29 | #define const_1 (bk/255.) 30 | #define constrast (255.0/(wh-bk)) 31 | 32 | float4 main(float2 tex: TEXCOORD0): COLOR { 33 | float4 c0 = tex2D(s0, tex); 34 | 35 | c0.rgb = c0.rgb*constrast -const_1*constrast; 36 | return c0; 37 | } -------------------------------------------------------------------------------- /A-pack/Shaders/exposure.08.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Exposure 0.08 3 | 4 | /* --- bExposure (dx9) --- */ 5 | /* v1.40 (07/2023) released by butterw under GPLv3 6 | /* (1 texture, 1 arithmetic) 7 | 8 | Exposure increases (or decreases) contrast/brightness. 9 | 10 | out = x * (1 + Exposure) = x + x*Exposure 11 | with x, out: pixel.rgb in [0, 1.0] 12 | 13 | Exposure doesn't affect the Black point (0, 0). 14 | - Contrast: 1+Exposure. 15 | - Brightness change: Exposure*x. Maximum at the White point. 16 | 17 | - parameter Exposure, [-1.0, ..], 0: no change, -1: All black 18 | >> Positive: increases contrast/brightness, ex: 0.08 19 | ! input> 1/(1+Exposure) will be clipped. 20 | 21 | negative: decreases contrast/brightness (dims), output<= 1+Exposure. 22 | 23 | */ 24 | sampler s0: register(s0); 25 | 26 | float4 main(float2 tex: TEXCOORD0): COLOR { 27 | float4 c0 = tex2D(s0, tex); 28 | 29 | c0.rgb = c0.rgb *(1.0 + Exposure); 30 | return c0; 31 | } -------------------------------------------------------------------------------- /A-pack/Shaders/sCurve.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define S 0.05 3 | 4 | /* --- sCurve (dx9) --- */ 5 | /* v1.40 (2023-11) released by butterw under GPLv3 6 | (1 texture, 12 arithmetic) 7 | 8 | Boosts (or reduces) midtone contrast by applying a blended s-curve (based on a Sigmoid). 9 | - With S>0: 10 | Reduces contrast in darks and brights, but doesn't clip them. For small values of S, brightness of darks and brights isn't affected much. 11 | When clipping is undesirable, an S-curve provides a good alternative to a broader contrast.10 (or expand10_245) adjustment. 12 | 13 | - With S<0: inverse S-curve. 14 | reduces midtone contrast, but increases contrast in darks and brights. 15 | 16 | Sigmoid equation 17 | out = 1.0/( 1.0 + exp(-14*x +7.0) ) = 1.0/( 1.0 + exp(-14(x-0.5)) 18 | with x, out: pixel.rgb in [0, 1.0]. 19 | 20 | The curve is symmetrical around the midpoint (x=0.5) and doesn't change the Black point (x=0) or White point (x=1). 21 | Contrast boost at the midpoint: S*2.5. 22 | Contrast degradation at the Black and White points: S. 23 | 24 | parameter S, Blending Strength, [-1.0, 1.0], 0: no effect, typ: [-0.2, 0.2] 25 | - Positive: increases midtone contrast, ex:0.05 26 | Not good with dark scenes, especially with higher values of S, because of the reduced contrast (and brightness) in Shadows. 27 | It is not typically necessary to increase contrast for movies (though a low Strength s-curve adjustment could be beneficial in special cases, ex: faded colors in older films). 28 | 29 | Alternative s-curve equation 30 | out = 0.5 + x1/( 0.5 + abs(x1) ) 31 | with x1 = x - 0.5. 32 | This is curve #2 in sweetfx.curves. ex: s2(0.125) 33 | slightly simpler to calculate, (1 texture, 9 arithmetic). Sigmoid has higher peak contrast boost, and less contrast/brightness degradation in darks, but the midtone contrast boost is also narrower. 34 | Contrast boost at the midpoint: S. 35 | Contrast degradation at the Black and White points: S/2. 36 | 37 | */ 38 | sampler s0: register(s0); 39 | 40 | float4 main(float2 tex: TEXCOORD0): COLOR { 41 | float4 c0 = tex2D(s0, tex); 42 | 43 | c0.rgb = lerp(c0.rgb, 1.0/( 1.0 + exp(-14*c0.rgb +7.0) ), S); 44 | return c0; 45 | } -------------------------------------------------------------------------------- /A-pack/Shaders/tooBright.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Multiply 0.20 3 | 4 | /* --- tooBright (dx9) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 3 arithmetic) 7 | 8 | Apply when the picture is too bright. 9 | Decreases brightness without clipping (Black point and White point are not changed). 10 | 11 | Photoshop Multiply Blend, brightness/contrast curve: 12 | out = (1-Multiply)*x + Multiply*x*x = Multiply*x^2 -Multiply*x +x 13 | with x, out: pixel.rgb in [0, 1.0] 14 | and Multiply>=0 15 | 16 | parameter Multiply [-1, 1.0], 0: no effect. 17 | >> Positive: (Multiply Blend) decreases brightness. Increases contrast in highlights. ex: 0.20 18 | - Brightness decrease is maximum at the mid-point (-Multiply/4). 19 | - Contrast = 2*Multiply*x +1-Multiply 20 | Contrast increases linearly with input level and is maximum at the White point (1+Multiply). 21 | Contrast: 1 at the mid-point. 22 | 23 | negative: (Screen Blend) increases brightness. 24 | 25 | */ 26 | sampler s0: register(s0); 27 | 28 | 29 | float4 main(float2 tex: TEXCOORD0): COLOR { 30 | float4 c0 = tex2D(s0, tex); 31 | 32 | c0.rgb = lerp(c0, c0*c0, Multiply).rgb; 33 | return c0; 34 | } -------------------------------------------------------------------------------- /A-pack/Shaders/tooDark.12.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Screen 0.12 3 | 4 | /* --- tooDark (dx9) small adjustment, ex: 0.12 --- */ 5 | /* These parameters provides a small brightness increase to boost a clip that could maybe be brighter. 6 | If clipping highlights isn't an issue, alternatives would be: brightenD.03 7 | or for a brightness+contrast increase: exposure.04. 8 | --- 9 | v1.40 (2023-07) released by butterw under GPLv3 10 | (1 texture, 3 arithmetic) 11 | 12 | Apply when the picture is too dark. 13 | Increases brightness without clipping (Black point and White point are not changed). 14 | 15 | Photoshop Screen Blend, brightness/contrast curve: 16 | out = -Screen*x*x + (1+Screen)*x = -Screen*x^2 +Screen*x + x 17 | with x, out: pixel.rgb in [0, 1.0] 18 | and Screen >=0 19 | 20 | parameter Screen [-1, 1.0], 0: no effect. 21 | >> Positive: (Screen Blend) increases brightness, increases constrast in shadows, ex: 0.24 22 | - Brightness increase is maximum at the mid-point (Screen/4). 23 | - Contrast = 1+Screen -2*Screen*x 24 | Contrast is maximum at the Black point (1+Screen) and decreases linearly with input level. 25 | Contrast:1 at the mid-point. 26 | 27 | negative: (Multiply Blend) decreases brightness, increases contrast in highlights. 28 | 29 | */ 30 | sampler s0: register(s0); 31 | #define Multiply -Screen //to ensure a positive user parameter. 32 | 33 | float4 main(float2 tex: TEXCOORD0): COLOR { 34 | float4 c0 = tex2D(s0, tex); 35 | 36 | c0.rgb = lerp(c0, c0*c0, Multiply).rgb; 37 | return c0; 38 | } -------------------------------------------------------------------------------- /A-pack/Shaders/tooDark.24.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Screen 0.24 3 | 4 | /* --- tooDark (dx9) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 3 arithmetic) 7 | 8 | Apply when the picture is too dark. 9 | Increases brightness without clipping (Black point and White point are not changed). 10 | 11 | Photoshop Screen Blend, brightness/contrast curve: 12 | out = -Screen*x*x + (1+Screen)*x = -Screen*x^2 +Screen*x + x 13 | with x, out: pixel.rgb in [0, 1.0] 14 | and Screen >=0 15 | 16 | parameter Screen [-1, 1.0], 0: no effect. 17 | >> Positive: (Screen Blend) increases brightness, increases constrast in shadows, ex: 0.24 18 | - Brightness increase is maximum at the mid-point (Screen/4). 19 | - Contrast = 1+Screen -2*Screen*x 20 | Contrast is maximum at the black point (1+Screen) and decreases linearly with input level. 21 | Contrast:1 at the mid-point. 22 | 23 | negative: (Multiply Blend) decreases brightness, increases contrast in highlights. 24 | 25 | */ 26 | sampler s0: register(s0); 27 | #define Multiply -Screen //to ensure a positive user parameter. 28 | 29 | float4 main(float2 tex: TEXCOORD0): COLOR { 30 | float4 c0 = tex2D(s0, tex); 31 | 32 | c0.rgb = lerp(c0, c0*c0, Multiply).rgb; 33 | return c0; 34 | } -------------------------------------------------------------------------------- /A-pack/Shaders/tooDark.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Multiply -0.3 3 | 4 | /* --- tooDark (dx9) --- */ 5 | 6 | /* v1.30 (2023-07) released by butterw under GPLv3 7 | (1 texture, 3 arithmetic) 8 | 9 | 10 | Photoshop Screen or Multiply Blend brightness/contrast curves 11 | c0 = (1-Multiply)*c0 + Multiply*c0*c0 12 | with c0: pixel.rgb in [0, 1.0] 13 | 14 | parameter Multiply [-1, 1], 0: no effect 15 | positive: (Multiply Blend) decreases brightness and increases contrast in highlights without clipping. 16 | negative: (Screen Blend) increases brightness and constrast in shadows without clipping. 17 | Apply when picture is too dark. ex: Outdoor night shots, ex: -0.3. 18 | 19 | */ 20 | 21 | sampler s0: register(s0); 22 | 23 | 24 | float4 main(float2 tex: TEXCOORD0): COLOR { 25 | float4 c0 = tex2D(s0, tex); 26 | 27 | c0.rgb = lerp(c0, c0*c0, Multiply).rgb; 28 | return c0; 29 | } -------------------------------------------------------------------------------- /A-pack/Shaders/vibrance-15.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Vibrance -0.15 3 | 4 | /* --- vibrance (dx9) --- */ 5 | /* v1.10 (2023-06) released by butterw under GPLv3 6 | simplified version of SweetFx.Vibrance 7 | (1 texture, 10 arithmetic) 8 | 9 | - Vibrance parameter, [-1.0, ..], 0: no effect 10 | positive: saturates low-saturation pixels more 11 | negative: reduces saturation of high-saturation pixels more, ex: -0.15 12 | */ 13 | 14 | sampler s0 : register(s0); 15 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 16 | 17 | 18 | float4 main(float2 tex : TEXCOORD0) : COLOR { 19 | float4 c0 = tex2D(s0, tex); 20 | 21 | float2 colorxy = (c0.r > c0.g) ? c0.gr: c0.rg; 22 | float colorSat = max(c0.b, colorxy.y) -min(c0.b, colorxy.x); // max3(r,g,b)-min3(r,g,b): >0 23 | c0.rgb = lerp(dot(CoefLuma, c0), c0.rgb, 1.0+Vibrance-colorSat*abs(Vibrance)); 24 | 25 | return c0; 26 | } -------------------------------------------------------------------------------- /A-pack/Shaders/vibrance.35.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define Vibrance 0.35 3 | 4 | /* --- vibrance (dx9) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 9 arithmetic). 7 | 8 | Smart saturation (or desaturation). Protects skin tones from excessive adjustments. 9 | 10 | - Vibrance parameter, [-1, 1.0], 0: no effect 11 | >> Positive: saturates low-saturation pixels first, ex: 0.35 12 | negative: reduces saturation of high-saturation pixels first, ex: -0.15 13 | 14 | Simplified version of SweetFx.Vibrance. 15 | Calculates a saturation measure, then applies saturation based on it. 16 | Affects color only, no effect on grays. 17 | */ 18 | 19 | sampler s0: register(s0); 20 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 21 | 22 | float4 main(float2 tex: TEXCOORD0): COLOR { 23 | float4 c0 = tex2D(s0, tex); 24 | float colorSat = max(max(c0.r, c0.g), c0.b) - min(min(c0.r, c0.g), c0.b); // >=0, 5 arithmetic 25 | 26 | colorSat = 1.0+Vibrance -abs(Vibrance)*colorSat; 27 | c0.rgb = lerp(dot(c0, CoefLuma), c0.rgb, colorSat); 28 | return c0; 29 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/bDim-35.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Exposure -0.35 3 | 4 | /* --- bExposure (dx11) --- */ 5 | /* v1.01 (06/2023) released by butterw under GPLv3 6 | (1 texture, 1 arithmetic) 7 | 8 | Dims or lights-up the video. 9 | 10 | c0 = c0 *(1.0+Exposure) = c0 + c0*Exposure, with c0: pixel.rgb 11 | - parameter Exposure, [-1, ..], 0: no change, -1: All black. 12 | negative: dims, ex: -0.35 13 | positive: lights-up 14 | 15 | */ 16 | 17 | 18 | Texture2D tex : register(t0); 19 | SamplerState samp : register(s0); 20 | 21 | float4 main(float4 pos : SV_POSITION, float2 coord : TEXCOORD) : SV_Target { 22 | float4 c0 = tex.Sample(samp, coord); 23 | 24 | return c0 *(1.0 + Exposure); 25 | } 26 | -------------------------------------------------------------------------------- /A-pack/Shaders11/bLift.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Lift 0.05 3 | 4 | /* --- bLift (dx11) --- */ 5 | /* v1.0 (2023-06) released by butterw under GPLv3 6 | 7 | pixel.rgb = pixel.rgb*(1 -0.5*Lift) +0.5*Lift 8 | - rgb Lift Parameter (default value: 0.05) 9 | negative: darkens the image, 0: no change, positive: lightens the image 10 | 11 | Lift limits image burn-out vs a brightness adjustment (rgb shift): 12 | pixel.rgb = pixel.rgb + Brightness 13 | */ 14 | 15 | Texture2D tex : register(t0); 16 | SamplerState samp : register(s0); 17 | 18 | float4 main(float4 pos : SV_POSITION, float2 coord : TEXCOORD) : SV_Target { 19 | float4 c0 = tex.Sample(samp, coord); 20 | 21 | return c0*(1 -0.5*Lift) +0.5*Lift; 22 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/bShadows-08.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Shadows -0.08 3 | 4 | /* --- bShadows (dx11) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 5 arithmetic) 7 | 8 | Darken (or lighten) the shadows. 9 | 10 | out = x + Shadows*(1-x)^4 11 | with x, out: pixel.rgb in [0, 1.0]. 12 | 13 | - parameter Shadows [-1, 1.0], 0: no change 14 | >> Negative: darkens the shadows, ex: -0.10 15 | Use to ensure shadows are darks, doesn't alter the rest of the picture. 16 | Can be used to correct raised black levels. 17 | for Shadows:-0.10, clipped input <0.0736, first order approximation: clips > Positive: increases the contrast, ex: 0.10 20 | brightness is increased above the mid-point, and decreased below the mid-point. 21 | ! input will be clipped: 22 | < Contrast/2. *1/(1+Contrast) 23 | > 1-Contrast/2. *1/(1+Contrast) 24 | for Contrast 0.10: clips <0.0455 and >0.954 25 | 26 | negative: decreases the contrast. 27 | 28 | */ 29 | Texture2D tex: register(t0); 30 | SamplerState samp: register(s0); 31 | 32 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 33 | float4 c0 = tex.Sample(samp, coord); 34 | 35 | c0.rgb = c0.rgb*(1 +Contrast) -0.5*Contrast; 36 | return c0; 37 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/dSat.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define SatFactor -0.25 3 | 4 | /* --- dSat (dx9) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 3 arithmetic) 7 | 8 | A lightweight desaturation shader with a touch of red exposure to avoid pasty grey skintones. 9 | faster than vibrance-15. 10 | 11 | param SatFactor [-1, ..], 0: no Effect, -1: Gray 12 | negative: desaturation, ex:-0.25 13 | 14 | */ 15 | #define rExposure float3(0.05, 0.008, 0) 16 | #define LumaCoef float4(0.2126, 0.7152, 0.0722, 0) 17 | 18 | Texture2D tex: register(t0); 19 | SamplerState samp: register(s0); 20 | 21 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 22 | float4 c0 = tex.Sample(samp, coord); 23 | 24 | float gray = dot(c0, LumaCoef); 25 | c0 = lerp(gray, c0, 1.0 + SatFactor); 26 | c0.rgb = c0.rgb *(1.0 + rExposure); 27 | return c0; 28 | } 29 | -------------------------------------------------------------------------------- /A-pack/Shaders11/deContrast.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define S -0.07 3 | #define n 4 4 | 5 | /* --- deContrast (dx11) --- */ 6 | 7 | /* v1.50 (2023-11) released by butterw under GPLv3 8 | (with S<0, ex: -0.07) Reduces midtone contrast. Also boosts contrast in shadows/highlights. 9 | n:4 (1 texture, 6 arithmetic). 10 | 11 | # Sn brightness/contrast curve 12 | out = f(x, S) = x + S/2*(2*x-1) *(1-(2*x-1)^n) = x + S/2*x1 *(1-x1^n) 13 | with n even >0 (ex: 4, 6, 8, 16, etc.) 14 | and x1 = 2*x -1 15 | and x, out pixel.rgb in [0, 1.0]. 16 | 17 | # Brightness 18 | f(x:0)=0; f(0.5)=0.5; f(1)=1. 19 | S<0: brightness is increased below the midpoint (x: 0.5) and decreased above the midpoint. 20 | 21 | # Contrast 22 | - contrast(x:0.5): 1+S 23 | - contrast(x:0)=contrast(x:1): 1-S*n 24 | 25 | 26 | Parameter S [-0.15, 0.15], 0: no effect 27 | - S>0: This symmetrical S-curve is a smoothed version of the contrast/levels linear curve. It provide a constant contrast increase (S) for a wide midtone range (with n=4+), and while it doesn't clip, contrast is decreased (up to S*n) in the highlights/shadows region. Because of this the sigmoid (sCurve shader) is probably a better choice for increasing contrast. 28 | - S<0: inverse S-curve. Now contrast is decreased by a constant value (S) in a wide midtone range and contrast is increased in the Shadows/Highlights (by |S|*n at x=0 and x=1). 29 | The plot https://github.com/butterw/bShaders/blob/master/img/deContrast_vs_contrast.png compares the contrast for different adjustment methods. This shader can be used to correct over-contrasted videos to get a more natural looking result. It's also good for restoring contrast/improving brightness in dark or bright videos. 30 | 31 | Parameter n, even integer [4: default, 8, 16, 6, ..] 32 | The higher n is, the wider the midtone contrast decrease range (with S<0) but also the stronger the contrast increase in highlights/shadows. 33 | n:8 (1 texture, 7 arithmetic) 34 | n:4 (1 texture, 6 arithmetic), default 35 | n:2 (1 texture, 5 arithmetic), S3(S/2) Hermite smoothstep interpolation. no flat midtone contrast decrease range. 36 | */ 37 | Texture2D tex: register(t0); 38 | SamplerState samp: register(s0); 39 | 40 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 41 | float4 c0 = tex.Sample(samp, coord); 42 | 43 | float3 c1 = 2*c0.rgb -1; 44 | c0.rgb+= 0.5*S *c1 *( 1.0 -pow(c1, n) ); 45 | return c0; 46 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/expand10_240.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define bk 10 3 | #define wh 240 4 | 5 | /* --- expandB_W (dx11) xB_W --- */ 6 | /* v1.40 (07/2023) released by butterw under GPLv3 7 | (1 texture, 1 arithmetic) 8 | 9 | Expands the rgb histogram by applying the levels curve, increasing the contrast. 10 | Can be useful to lift the haze on lackluster internet videos. 11 | 12 | ! Parameter values (bk, wh) use rgb8 color scale [0, 255.0], not [0, 1.0]. 13 | bk: new Black point, wh: new White point, (bk:0, wh:255): no effect 14 | ! Any input below bk, or above wh will be clipped. 15 | 16 | Modified version of the MPC-HC shader "16-235 to 0-255.hlsl". 17 | allows custom values instead of (16, 235) for the new rgb Black/White points 18 | ex: (bk: 10, wh: 240), contrast=1.109 19 | The 2 parameters allow for asymmetrical expansion (bk!= 255-wh) which is not available with the (single parameter) constrast shader. 20 | 21 | Levels curve is a linear equation: 22 | out = (x -const_1) *contrast = x*contrast -const_1*contrast 23 | with contrast = 255.0/(wh-bk) 24 | and x, out: input, output pixel.rgb in [0, 1.0]. 25 | out = (x*255. -bk) /(wh-bk) 26 | 27 | */ 28 | Texture2D tex: register(t0); 29 | SamplerState samp: register(s0); 30 | #define const_1 (bk/255.) 31 | #define constrast (255.0/(wh-bk)) 32 | 33 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 34 | float4 c0 = tex.Sample(samp, coord); 35 | 36 | c0.rgb = c0.rgb*constrast -const_1*constrast; 37 | return c0; 38 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/exposure.08.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Exposure 0.08 3 | 4 | /* --- bExposure (dx11) --- */ 5 | /* v1.40 (07/2023) released by butterw under GPLv3 6 | /* (1 texture, 1 arithmetic) 7 | 8 | Exposure increases (or decreases) contrast/brightness. 9 | 10 | out = x * (1 + Exposure) = x + x*Exposure 11 | with x, out: pixel.rgb in [0, 1.0] 12 | 13 | Exposure doesn't affect the Black point (0, 0). 14 | - Contrast: 1+Exposure. 15 | - Brightness change: Exposure*x. Maximum at the White point. 16 | 17 | - parameter Exposure, [-1.0, ..], 0: no change, -1: All black 18 | >> Positive: increases contrast/brightness, ex: 0.08 19 | ! input> 1/(1+Exposure) will be clipped. 20 | 21 | negative: decreases contrast/brightness (dims), output<= 1+Exposure. 22 | 23 | */ 24 | Texture2D tex: register(t0); 25 | SamplerState samp: register(s0); 26 | 27 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 28 | float4 c0 = tex.Sample(samp, coord); 29 | 30 | c0.rgb = c0.rgb *(1.0 + Exposure); 31 | return c0; 32 | } 33 | -------------------------------------------------------------------------------- /A-pack/Shaders11/sCurve.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define S 0.05 3 | 4 | /* --- sCurve (dx11) --- */ 5 | /* v1.40 (2023-11) released by butterw under GPLv3 6 | (1 texture, 12 arithmetic) 7 | 8 | Boosts (or reduces) midtone contrast by applying a blended s-curve (based on a Sigmoid). 9 | - With S>0: 10 | Reduces contrast in darks and brights, but doesn't clip them. For small values of S, brightness of darks and brights isn't affected much. 11 | When clipping is undesirable, an S-curve provides a good alternative to a broader contrast.10 (or expand10_245) adjustment. 12 | 13 | - With S<0: inverse S-curve. 14 | reduces midtone contrast, but increases contrast in darks and brights. 15 | 16 | Sigmoid equation 17 | out = 1.0/( 1.0 + exp(-14*x +7.0) ) = 1.0/( 1.0 + exp(-14(x-0.5)) 18 | with x, out: pixel.rgb in [0, 1.0]. 19 | 20 | The curve is symmetrical around the midpoint (x=0.5) and doesn't change the Black point (x=0) or White point (x=1). 21 | Contrast boost at the midpoint: S*2.5. 22 | Contrast degradation at the Black and White points: S. 23 | 24 | parameter S, Blending Strength, [-1.0, 1.0], 0: no effect, typ: [-0.2, 0.2] 25 | - Positive: increases midtone contrast, ex:0.05 26 | Not good with dark scenes, especially with higher values of S, because of the reduced contrast (and brightness) in Shadows. 27 | It is not typically necessary to increase contrast for movies (though a low Strength s-curve adjustment could be beneficial in special cases, ex: faded colors in older films). 28 | 29 | Alternative s-curve equation 30 | out = 0.5 + x1/( 0.5 + abs(x1) ) 31 | with x1 = x - 0.5. 32 | This is curve #2 in sweetfx.curves. ex: s2(0.125) and is slightly simpler to calculate, (1 texture, 9 arithmetic). 33 | Sigmoid has higher peak contrast boost, and less contrast/brightness degradation in darks, but has a narrower midtone contrast boost. 34 | Contrast boost at the midpoint: S. 35 | Contrast degradation at the Black and White points: S/2. 36 | 37 | */ 38 | Texture2D tex: register(t0); 39 | SamplerState samp: register(s0); 40 | 41 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 42 | float4 c0 = tex.Sample(samp, coord); 43 | 44 | c0.rgb = lerp(c0.rgb, 1.0/( 1.0 + exp(-14*c0.rgb +7.0) ), S); 45 | return c0; 46 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/tooBright.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Multiply 0.20 3 | 4 | /* --- tooBright (dx11) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 3 arithmetic) 7 | 8 | Apply when the picture is too bright. 9 | Decreases brightness without clipping (Black point and White point are not changed). 10 | 11 | Photoshop Multiply Blend, brightness/contrast curve: 12 | out = (1-Multiply)*x + Multiply*x*x = Multiply*x^2 -Multiply*x +x 13 | with x, out: pixel.rgb in [0, 1.0] 14 | and Multiply>=0 15 | 16 | parameter Multiply [-1, 1.0], 0: no effect. 17 | >> Positive: (Multiply Blend) decreases brightness. Increases contrast in highlights. ex: 0.20 18 | - Brightness decrease is maximum at the mid-point (-Multiply/4). 19 | - Contrast = 2*Multiply*x +1-Multiply 20 | Contrast increases linearly with input level and is maximum at the White point (1+Multiply). 21 | Contrast: 1 at the mid-point. 22 | 23 | negative: (Screen Blend) increases brightness. 24 | 25 | */ 26 | 27 | Texture2D tex: register(t0); 28 | SamplerState samp: register(s0); 29 | 30 | 31 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 32 | float4 c0 = tex.Sample(samp, coord); 33 | 34 | c0.rgb = lerp(c0, c0*c0, Multiply).rgb; 35 | return c0; 36 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/tooDark-30.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Multiply -0.30 3 | 4 | /* --- tooDark (dx11) --- */ 5 | /* v1.35 (2023-07) released by butterw under GPLv3 6 | (1 texture, 3 arithmetic) 7 | 8 | Apply when the picture is too dark. 9 | Black and White point are not changed (no clipping). 10 | 11 | Photoshop Screen Blend, brightness/contrast curve: 12 | c0 = (1-Multiply)*c0 + Multiply*c0*c0 13 | with c0: pixel.rgb in [0, 1.0] 14 | and Multiply<=0 15 | 16 | parameter Multiply [-1, 1.0], 0: no effect. 17 | >> negative: (Screen Blend) increases brightness, increases constrast in shadows, ex: -0.30 18 | - Brightness increase is maximum at the mid-point. 19 | - Contrast = 2*Multiply*c0+1-Multiply 20 | Contrast is maximum: (1-Multiply) at the black point and decreases linearly with input level. 21 | Contrast:1 at the mid-point. 22 | positive: (Multiply Blend) decreases brightness, increases contrast in highlights. 23 | 24 | */ 25 | Texture2D tex: register(t0); 26 | SamplerState samp: register(s0); 27 | 28 | 29 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 30 | float4 c0 = tex.Sample(samp, coord); 31 | 32 | c0.rgb = lerp(c0, c0*c0, Multiply).rgb; 33 | return c0; 34 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/tooDark.24.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Screen 0.24 3 | 4 | /* --- tooDark (dx11) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 3 arithmetic) 7 | 8 | Apply when the picture is too dark. 9 | Increases brightness without clipping (Black point and White point are not changed). 10 | 11 | Photoshop Screen Blend, brightness/contrast curve: 12 | out = -Screen*x*x + (1+Screen)*x = -Screen*x^2 +Screen*x + x 13 | with x, out: pixel.rgb in [0, 1.0] 14 | and Screen >=0 15 | 16 | parameter Screen [-1, 1.0], 0: no effect. 17 | >> Positive: (Screen Blend) increases brightness, increases constrast in shadows, ex: 0.24 18 | - Brightness increase is maximum at the mid-point (Screen/4). 19 | - Contrast = 1+Screen -2*Screen*x 20 | Contrast is maximum at the Black point (1+Screen) and decreases linearly with input level. 21 | Contrast:1 at the mid-point. 22 | 23 | negative: (Multiply Blend) decreases brightness, increases contrast in highlights. 24 | 25 | */ 26 | Texture2D tex: register(t0); 27 | SamplerState samp: register(s0); 28 | #define Multiply -Screen //to ensure a positive user parameter. 29 | 30 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 31 | float4 c0 = tex.Sample(samp, coord); 32 | 33 | c0.rgb = lerp(c0, c0*c0, Multiply).rgb; 34 | return c0; 35 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/vibrance-15.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Vibrance -0.15 3 | 4 | /* --- vibrance (dx11) --- */ 5 | /* v1.10 (2023-06) released by butterw under GPLv3 6 | simplified version of SweetFx.Vibrance 7 | (1 texture, 10 arithmetic) 8 | 9 | - Vibrance parameter, [-1.0, ..], 0: no effect 10 | positive: saturates low-saturation pixels more 11 | negative: reduces saturation of high-saturation pixels more, ex: -0.15 12 | */ 13 | 14 | Texture2D tex : register(t0); 15 | SamplerState samp : register(s0); 16 | 17 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 18 | 19 | float4 main(float4 pos : SV_POSITION, float2 coord : TEXCOORD) : SV_Target { 20 | float4 c0 = tex.Sample(samp, coord); 21 | 22 | 23 | float2 colorxy = (c0.r > c0.g) ? c0.gr: c0.rg; 24 | float colorSat = max(c0.b, colorxy.y) -min(c0.b, colorxy.x); // max3(r,g,b)-min3(r,g,b): >0 25 | c0.rgb = lerp(dot(CoefLuma, c0), c0.rgb, 1.0+Vibrance-colorSat*abs(Vibrance)); 26 | 27 | return c0; 28 | } -------------------------------------------------------------------------------- /A-pack/Shaders11/vibrance.35.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Vibrance 0.35 3 | 4 | /* --- vibrance (dx11) --- */ 5 | /* v1.40 (2023-07) released by butterw under GPLv3 6 | (1 texture, 9 arithmetic). 7 | 8 | Smart saturation (or desaturation). Protects skin tones from excessive adjustments. 9 | 10 | - Vibrance parameter, [-1, 1.0], 0: no effect 11 | >> Positive: saturates low-saturation pixels first, ex: 0.35 12 | negative: reduces saturation of high-saturation pixels first, ex: -0.15 13 | 14 | Simplified version of SweetFx.Vibrance. 15 | Calculates a saturation measure, then applies saturation based on it. 16 | Affects color only, no effect on grays. 17 | */ 18 | 19 | Texture2D tex: register(t0); 20 | SamplerState samp: register(s0); 21 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 22 | 23 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 24 | float4 c0 = tex.Sample(samp, coord); 25 | 26 | float colorSat = max(max(c0.r, c0.g), c0.b) - min(min(c0.r, c0.g), c0.b); // >=0, 5 arithmetic 27 | colorSat = 1.0+Vibrance -abs(Vibrance)*colorSat; 28 | c0.rgb = lerp(dot(c0, CoefLuma), c0.rgb, colorSat); 29 | return c0; 30 | } -------------------------------------------------------------------------------- /A-pack/mpv/bDim-35.hook: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC bDim 4 | 5 | #define Exposure -0.35 6 | 7 | /* --- bDim (mpv .hook) --- */ 8 | /* v1.01 (06/2023) released by butterw under GPLv3 9 | (1 texture, 1 arithmetic) 10 | 11 | Dims or lights-up the video. 12 | 13 | c0 = c0 *(1.0+Exposure) = c0 + c0*Exposure, with c0: pixel.rgb 14 | - parameter Exposure, [-1, ..], 0: no change, -1: All black. 15 | negative: dims, ex: -0.35 16 | positive: lights-up 17 | 18 | */ 19 | 20 | vec4 hook() { 21 | vec4 c0 = HOOKED_texOff(0); 22 | return c0 *(1.0 + Exposure); 23 | } -------------------------------------------------------------------------------- /A-pack/mpv/bLift.hook: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC bLift 4 | 5 | #define Lift 0.05 6 | 7 | /* --- bLift (mpv .hook) --- */ 8 | /* released under GPLv3 9 | 10 | pixel.rgb = pixel.rgb*(1 -0.5*Lift) +0.5*Lift 11 | - Lift Parameter [-1, 1], 0: no change 12 | negative: darkens the image, 0: no change, 13 | positive: lightens the image, ex=0.05 14 | 15 | */ 16 | 17 | vec4 hook() { 18 | vec4 c0 = HOOKED_texOff(0); 19 | return c0*(1 -0.5*Lift) +0.5*Lift; 20 | } -------------------------------------------------------------------------------- /A-pack/mpv/bShadows-08.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC bShadows 4 | 5 | #define Shadows -0.08 6 | 7 | /* --- bShadows (mpv .hook) --- */ 8 | /* v1.40 (2023-07) released by butterw under GPLv3 9 | (1 texture, 5 arithmetic) 10 | 11 | Darken (or lighten) the shadows. 12 | 13 | out = x + Shadows*(1-x)^4 14 | with x, out: pixel.rgb in [0, 1.0]. 15 | 16 | - parameter Shadows [-1, 1.0], 0: no change 17 | >> Negative: darkens the shadows, ex: -0.08 18 | Use to ensure shadows are darks, doesn't alter the rest of the picture. 19 | Can be used to correct raised black levels. 20 | for Shadows:-0.10, clipped input <0.0736 21 | first order approximation: clips > Positive: increases the contrast, ex: 0.10 23 | brightness is increased above the mid-point, and decreased below the mid-point. 24 | ! input will be clipped: 25 | < Contrast/2. *1/(1+Contrast) 26 | > 1-Contrast/2. *1/(1+Contrast) 27 | for Contrast 0.10: clips <0.0455 and >0.954 28 | 29 | negative: decreases the contrast. 30 | 31 | */ 32 | 33 | vec4 hook() { 34 | vec4 c0 = HOOKED_texOff(0); 35 | 36 | c0.rgb = c0.rgb*(1.0 + Contrast) -0.5*Contrast; 37 | return c0; 38 | } -------------------------------------------------------------------------------- /A-pack/mpv/dSat.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC dSat 4 | 5 | #define SatFactor -0.25 6 | 7 | /* --- dSat (mpv glsl .hook) --- */ 8 | /* v1.40 (2023-07) released by butterw under GPLv3 9 | (1 texture, 3 arithmetic) 10 | 11 | A lightweight desaturation shader with a touch of red exposure to avoid pasty grey skintones. 12 | faster than vibrance-15. 13 | 14 | param SatFactor [-1.0, 0], 0: no Effect, -1: Gray 15 | negative: desaturation, ex:-0.25 16 | 17 | */ 18 | #define rExposure vec3(0.05, 0.008, 0) 19 | #define LumaCoef vec4(0.2126, 0.7152, 0.0722, 0) 20 | 21 | vec4 hook(){ 22 | vec4 c0 = HOOKED_texOff(0); 23 | 24 | float gray = dot(c0, LumaCoef); 25 | c0.rgb = mix(vec3(gray), c0.rgb, 1.0 + SatFactor); 26 | c0.rgb = c0.rgb *(1.0 + rExposure); 27 | return c0; 28 | } -------------------------------------------------------------------------------- /A-pack/mpv/deContrast.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC deContrast 4 | 5 | #define S -0.07 6 | #define n 4 7 | 8 | /* --- deContrast (mpv glsl.hook) --- */ 9 | 10 | /* v1.50 (2023-11) released by butterw under GPLv3 11 | n:4 (1 texture, 6 arithmetic). 12 | (with S<0, ex: -0.07) Reduces midtone contrast. Also boosts contrast in shadows/highlights. 13 | 14 | # Sn brightness/contrast curve 15 | out = f(x, S) = x + S/2*(2*x-1) *(1-(2*x-1)^n) = x + S/2*x1 *(1-x1^n) 16 | with n even >0 (ex: 4, 6, 8, 16, etc.) 17 | and x1 = 2*x -1 18 | and x, out pixel.rgb in [0, 1.0]. 19 | 20 | # Brightness 21 | f(x:0)=0; f(0.5)=0.5; f(1)=1. 22 | S<0: brightness is increased below the midpoint (x: 0.5) and decreased above the midpoint. 23 | 24 | # Contrast 25 | - contrast(x:0.5): 1+S 26 | - contrast(x:0)=contrast(x:1): 1-S*n 27 | 28 | 29 | Parameter S [-0.15, 0.15], 0: no effect 30 | - S>0: This symmetrical S-curve is a smoothed version of the contrast/levels linear curve. It provide a constant contrast increase (S) for a wide midtone range (with n=4+), and while it doesn't clip, contrast is decreased (up to S*n) in the highlights/shadows region. Because of this the sigmoid (sCurve shader) is probably a better choice for increasing contrast. 31 | - S<0: inverse S-curve. Now contrast is decreased by a constant value (S) in a wide midtone range and contrast is increased in the Shadows/Highlights (by |S|*n at x=0 and x=1). 32 | The plot https://github.com/butterw/bShaders/blob/master/img/deContrast_vs_contrast.png compares the contrast for different adjustment methods. This shader can be used to correct over-contrasted videos to get a more natural looking result. It's also good for restoring contrast/improving brightness in dark or bright videos. 33 | 34 | Parameter n, even integer [4: default, 8, 16, 6, ..] 35 | The higher n is, the wider the midtone contrast decrease range (with S<0) but also the stronger the contrast increase in highlights/shadows. 36 | n:8 (1 texture, 7 arithmetic) 37 | n:4 (1 texture, 6 arithmetic), default 38 | n:2 (1 texture, 5 arithmetic), S3(S/2) Hermite smoothstep interpolation. no flat midtone contrast decrease range. 39 | */ 40 | 41 | vec4 hook(){ 42 | vec4 c0 = HOOKED_texOff(0); 43 | 44 | vec3 c1 = 2*c0.rgb -1; 45 | #if n == 2 46 | c0.rgb+= 0.5*S *c1 *( 1.0 -c1*c1); 47 | #elif n == 4 48 | vec3 c2 = c1*c1; 49 | c0.rgb+= 0.5*S *c1 *( 1.0 -c2*c2); 50 | #elif n == 8 51 | vec3 c2 = c1*c1; c2 = c2*c2; 52 | c0.rgb+= 0.5*S *c1 *( 1.0 -c2*c2); 53 | #else 54 | c0.rgb+= 0.5*S *c1 *( 1.0 -pow(c0, vec3(n)) ); 55 | #endif 56 | 57 | return c0; 58 | } -------------------------------------------------------------------------------- /A-pack/mpv/expand10_240.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC expand10_240 4 | 5 | #define bk 10 6 | #define wh 240 7 | 8 | /* --- expandB_W (mpv glsl.hook) xB_W --- */ 9 | /* v1.40 (07/2023) released by butterw under GPLv3 10 | (1 texture, 1 arithmetic) 11 | 12 | Expands the rgb histogram by applying the levels curve, increasing the contrast. 13 | Can be useful to lift the haze on lackluster internet videos. 14 | 15 | ! Parameter values (bk, wh) use rgb8 color scale [0, 255.0], not [0, 1.0]. 16 | bk: new Black point, wh: new White point, (bk:0, wh:255): no effect 17 | ! Any input below bk, or above wh will be clipped. 18 | 19 | Modified version of the MPC-HC shader "16-235 to 0-255.hlsl". 20 | allows custom values instead of (16, 235) for the new rgb Black/White points 21 | ex: (bk: 10, wh: 240), contrast=1.109 22 | The 2 parameters allow for asymmetrical expansion (bk!= 255-wh) which is not available with the (single parameter) constrast shader. 23 | 24 | Levels curve is a linear equation: 25 | out = (x -const_1) *contrast = x*contrast -const_1*contrast 26 | with contrast = 255.0/(wh-bk) 27 | and x, out: input, output pixel.rgb in [0, 1.0]. 28 | out = (x*255. -bk) /(wh-bk) 29 | 30 | */ 31 | #define const_1 ( bk/255.) 32 | #define constrast (255.0/(wh-bk)) 33 | 34 | vec4 hook() { 35 | vec4 c0 = HOOKED_texOff(0); 36 | 37 | c0.rgb = c0.rgb*constrast -const_1*constrast; 38 | return c0; 39 | } 40 | -------------------------------------------------------------------------------- /A-pack/mpv/exposure.08.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC Exposure 4 | 5 | #define Exposure 0.08 6 | 7 | /* --- bExposure (mpv .hook) expo --- */ 8 | /* v1.40 (07/2023) released by butterw under GPLv3 9 | /* (1 texture, 1 arithmetic) 10 | 11 | Exposure increases (or decreases) contrast/brightness. 12 | 13 | out = x * (1 + Exposure) = x + x*Exposure 14 | with x, out: pixel.rgb in [0, 1.0] 15 | 16 | Exposure doesn't affect the Black point (0, 0). 17 | - Contrast: 1+Exposure. 18 | - Brightness change: Exposure*x. Maximum at the White point. 19 | 20 | - parameter Exposure, [-1.0, ..], 0: no change, -1: All black 21 | >> Positive: increases contrast/brightness, ex: 0.08 22 | ! input> 1/(1+Exposure) will be clipped. 23 | 24 | negative: decreases contrast/brightness (dims), output<= 1+Exposure. 25 | 26 | */ 27 | 28 | vec4 hook() { 29 | vec4 c0 = HOOKED_texOff(0); 30 | 31 | c0.rgb = c0.rgb *(1.0 + Exposure); 32 | return c0; 33 | } -------------------------------------------------------------------------------- /A-pack/mpv/portable_config/input.conf: -------------------------------------------------------------------------------- 1 | # basic mpv input.conf example for use with A-pack Video Adjustment shaders 2 | # by butterw (2023-08-02) 3 | # tested on Windows with this file in mpv subfolder .\portable_config 4 | 5 | ## ignore default keybindings: 6 | 3 ignore #3 add brightness -1 7 | 4 ignore #4 add brightness 1 8 | 9 | ## Shaders (assumes shader files have been copied to mpv/s): 10 | # tip: it's easier to compare shaders if the video is paused. 11 | F1 cycle-values glsl-shaders s/bw_noChroma.hk s/bw.hk "" 12 | F2 cycle-values glsl-shaders s/dSat.hk s/vibrance.35.hk "" 13 | 14 | F3 cycle-values glsl-shaders s/bShadows-08.hk s/tooBright.hk s/contrast.10.hk "" 15 | F4 cycle-values glsl-shaders s/exposure.08.hk s/tooDark.12.hk s/tooDark.24.hk "" 16 | 17 | F5 change-list glsl-shaders toggle s/expand10_240.hk #toggle one shader on/off individually 18 | 19 | Shift+F1 show-text "scale: ${scale}\nShaders: ${glsl-shaders}" 3000; 20 | CTRL+DEL change-list glsl-shaders set "" #turns shaders off, current shaders are lost. 21 | 22 | CTRL+p script-message switch-shaders #defined in scripts/switch-shaders.js: toggles shaders on-off, off: saves current shaders 23 | 24 | ## User keybindings: 25 | KP0 no-osd seek 0 absolute ; set pause no 26 | -------------------------------------------------------------------------------- /A-pack/mpv/portable_config/scripts/switch-shaders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //* --- switch-shaders.js mpv script --- */ 4 | //* part of A-pack v1.40 by butterw 5 | //- modified from https://github.com/mpv-player/mpv/issues/8512 6 | // 7 | // This script extends the mpv video-player by providing a switch to disable/restore current shaders. 8 | // 9 | // To install, copy this file to the mpv subfolder: .\portable_config\scripts (assuming a Windows portable install). 10 | // Then add a keybinding for the switch (ex: CTRL+p) in input.conf, ex: 11 | // CTRL+p script-message switch-shaders 12 | // 13 | //* 14 | 15 | var shaders_status= [] 16 | mp.register_script_message("switch-shaders", function() { 17 | var shaders_str = mp.get_property("glsl-shaders"); 18 | if (!shaders_str.length && shaders_status.length) { //shaders-on: restore glsl-shaders (but only if empty!) 19 | shaders_status.forEach(function(shader) {mp.commandv("change-list", "glsl-shaders", "append", shader)}); 20 | mp.osd_message(mp.get_property("glsl-shaders"), 0.5) 21 | print("shaders-on:", shaders_status) 22 | shaders_status = [] 23 | } else { //shaders-off: store current glsl-shaders 24 | shaders_status = mp.get_property("glsl-shaders").split(',') 25 | mp.set_property("glsl-shaders", "") 26 | mp.osd_message("shaders-off", 0.5) 27 | //print("shaders-off", shaders_status) 28 | } 29 | }); 30 | 31 | var is_first_run = true 32 | var shaders = "" -------------------------------------------------------------------------------- /A-pack/mpv/sCurve.hk.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC sCurve (sigmoid) 4 | 5 | #define S 0.05 6 | /* --- sCurve (mpv glsl.hook) --- 7 | /* v1.40 (2023-11) released by butterw under GPLv3 8 | (1 texture, 12 arithmetic) 9 | 10 | Boosts (or reduces) midtone contrast by applying a blended s-curve (based on a Sigmoid). 11 | - With S>0: 12 | Reduces contrast in darks and brights, but doesn't clip them. For small values of S, brightness of darks and brights isn't affected much. 13 | When clipping is undesirable, an S-curve provides a good alternative to a broader contrast.10 (or expand10_245) adjustment. 14 | 15 | - With S<0: inverse S-curve. 16 | reduces midtone contrast, but increases contrast in darks and brights. 17 | 18 | Sigmoid equation 19 | out = 1.0/( 1.0 + exp(-14*x +7.0) ) = 1.0/( 1.0 + exp(-14(x-0.5)) 20 | with x, out: pixel.rgb in [0, 1.0]. 21 | 22 | The curve is symmetrical around the midpoint (x=0.5) and doesn't change the Black point (x=0) or White point (x=1). 23 | Contrast boost at the midpoint: S*2.5. 24 | Contrast degradation at the Black and White points: S. 25 | 26 | parameter S, Blending Strength, [-1.0, 1.0], 0: no effect, typ: [-0.2, 0.2] 27 | - Positive: increases midtone contrast, ex:0.05 28 | Not good with dark scenes, especially with higher values of S, because of the reduced contrast (and brightness) in Shadows. 29 | It is not typically necessary to increase contrast for movies (though a low Strength s-curve adjustment could be beneficial in special cases, ex: faded colors in older films). 30 | 31 | Alternative s-curve equation 32 | out = 0.5 + x1/( 0.5 + abs(x1) ) 33 | with x1 = x - 0.5. 34 | This is curve #2 in sweetfx.curves. ex: s2(0.125) and is slightly simpler to calculate, (1 texture, 9 arithmetic). 35 | Sigmoid has higher peak contrast boost, and less contrast/brightness degradation in darks, but has a narrower midtone contrast boost. 36 | Contrast boost at the midpoint: S. 37 | Contrast degradation at the Black and White points: S/2. 38 | 39 | */ 40 | vec4 hook(){ 41 | vec4 c0 = HOOKED_texOff(0); 42 | 43 | c0.rgb = mix(c0.rgb, 1/( 1.0 + exp(-14*c0.rgb +7) ), S); 44 | return c0; 45 | } 46 | -------------------------------------------------------------------------------- /A-pack/mpv/tooBright.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC tooBright 4 | #define Multiply 0.20 5 | 6 | /* --- tooBright (mpv glsl.hook) --- */ 7 | /* v1.40 (2023-07) released by butterw under GPLv3 8 | (1 texture, 3 arithmetic) 9 | 10 | Apply when the picture is too bright. 11 | Decreases brightness without clipping (Black point and White point are not changed). 12 | 13 | Photoshop Multiply Blend, brightness/contrast curve: 14 | out = (1-Multiply)*x + Multiply*x*x = Multiply*x^2 -Multiply*x +x 15 | with x, out: pixel.rgb in [0, 1.0] 16 | and Multiply>=0 17 | 18 | parameter Multiply [-1, 1.0], 0: no effect. 19 | >> Positive: (Multiply Blend) decreases brightness. Increases contrast in highlights. ex: 0.20 20 | - Brightness decrease is maximum at the mid-point (-Multiply/4). 21 | - Contrast = 2*Multiply*x +1-Multiply 22 | Contrast increases linearly with input level and is maximum at the White point (1+Multiply). 23 | Contrast: 1 at the mid-point. 24 | 25 | negative: (Screen Blend) increases brightness. 26 | 27 | */ 28 | vec4 hook() { 29 | vec4 c0 = HOOKED_texOff(0); 30 | 31 | c0.rgb = mix(c0, c0*c0, Multiply).rgb; 32 | return c0; 33 | } -------------------------------------------------------------------------------- /A-pack/mpv/tooDark.12.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC tooDark-12 4 | #define Screen 0.12 5 | 6 | /* --- tooDark (mpv glsl.hook) small adjustment, ex: 0.12 --- */ 7 | /* These parameters provides a small brightness increase to boost a clip that could maybe be brighter. 8 | If clipping highlights isn't an issue, alternatives would be: brightenD.03 9 | or for a brightness+contrast increase: exposure.04. 10 | --- 11 | v1.40 (2023-07) released by butterw under GPLv3 12 | (1 texture, 3 arithmetic) 13 | 14 | Apply when the picture is too dark. 15 | Increases brightness without clipping (Black point and White point are preserved). 16 | 17 | Photoshop Screen Blend, brightness/contrast curve: 18 | out = -Screen*x*x + (1+Screen)*x = -Screen*x^2 +Screen*x + x 19 | with x, out: pixel.rgb in [0, 1.0] 20 | and Screen >=0 21 | 22 | parameter Screen [-1, 1.0], 0: no effect. 23 | >> Positive: (Screen Blend) increases brightness, increases constrast in shadows, ex: 0.24 24 | - Brightness increase is maximum at the mid-point (Screen/4). 25 | - Contrast = 1+Screen -2*Screen*x 26 | Contrast is maximum at the Black point (1+Screen) and decreases linearly with input level. 27 | Contrast:1 at the mid-point. 28 | 29 | negative: (Multiply Blend) decreases brightness, increases contrast in highlights. 30 | 31 | */ 32 | #define Multiply -Screen //to ensure a positive user parameter. 33 | 34 | vec4 hook() { 35 | vec4 c0 = HOOKED_texOff(0); 36 | 37 | c0.rgb = mix(c0, c0*c0, Multiply).rgb; 38 | return c0; 39 | } -------------------------------------------------------------------------------- /A-pack/mpv/tooDark.24.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC tooDark-24 4 | #define Screen 0.24 5 | 6 | /* --- tooDark (mpv glsl.hook) --- */ 7 | /* v1.40 (2023-07) released by butterw under GPLv3 8 | (1 texture, 3 arithmetic) 9 | 10 | Apply when the picture is too dark. 11 | Increases brightness without clipping (Black point and White point are not changed). 12 | 13 | Photoshop Screen Blend, brightness/contrast curve: 14 | out = -Screen*x*x + (1+Screen)*x = -Screen*x^2 +Screen*x + x 15 | with x, out: pixel.rgb in [0, 1.0] 16 | and Screen >=0 17 | 18 | parameter Screen [-1, 1.0], 0: no effect. 19 | >> Positive: (Screen Blend) increases brightness, increases constrast in shadows, ex: 0.24 20 | - Brightness increase is maximum at the mid-point (Screen/4). 21 | - Contrast = 1+Screen -2*Screen*x 22 | Contrast is maximum at the Black point (1+Screen) and decreases linearly with input level. 23 | Contrast:1 at the mid-point. 24 | 25 | negative: (Multiply Blend) decreases brightness, increases contrast in highlights. 26 | 27 | */ 28 | #define Multiply -Screen //to ensure a positive user parameter. 29 | 30 | vec4 hook() { 31 | vec4 c0 = HOOKED_texOff(0); 32 | 33 | c0.rgb = mix(c0, c0*c0, Multiply).rgb; 34 | return c0; 35 | } -------------------------------------------------------------------------------- /A-pack/mpv/vibrance-15.hook: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC Vibrance 4 | 5 | #define Vibrance -0.15 6 | 7 | /* --- vibrance (mpv .hook) --- */ 8 | /* v1.0 (2023-06) released by butterw under GPLv3 9 | simplified version of SweetFx.Vibrance 10 | 11 | - Vibrance parameter, [-1.0, ..], 0: no effect 12 | positive: saturates low-saturation pixels 13 | negative: reduces saturation of high-saturation pixels, ex: -0.15 14 | */ 15 | 16 | #define CoefLuma vec4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 17 | 18 | vec4 hook() { 19 | vec4 c0 = HOOKED_texOff(0); 20 | 21 | vec2 colorxy = (c0.r > c0.g) ? c0.gr: c0.rg; 22 | float colorSat = max(c0.b, colorxy.y) - min(c0.b, colorxy.x); 23 | c0.rgb = mix(vec3(dot(c0, CoefLuma)), c0.rgb, 1+Vibrance -colorSat*abs(Vibrance)); 24 | return c0; 25 | } 26 | -------------------------------------------------------------------------------- /A-pack/mpv/vibrance.35.hk: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC Vibrance.35 4 | 5 | #define Vibrance 0.35 6 | 7 | /* --- vibrance (mpv glsl.hook) --- */ 8 | /* v1.40 (2023-07) released by butterw under GPLv3 9 | (1 texture, 9 arithmetic). 10 | 11 | Smart saturation (or desaturation). Protects skin tones from excessive adjustments. 12 | 13 | - Vibrance parameter, [-1, 1.0], 0: no effect 14 | >> Positive: saturates low-saturation pixels first, ex: 0.35 15 | negative: reduces saturation of high-saturation pixels first, ex: -0.15 16 | 17 | Simplified version of SweetFx.Vibrance. 18 | Calculates a saturation measure, then applies saturation based on it. 19 | Affects color only, no effect on grays. 20 | */ 21 | 22 | #define CoefLuma vec4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 23 | 24 | vec4 hook() { 25 | vec4 c0 = HOOKED_texOff(0); 26 | float colorSat = max(max(c0.r, c0.g), c0.b) - min(min(c0.r, c0.g), c0.b); // >=0, 5 arithmetic 27 | 28 | colorSat = 1.0+Vibrance -abs(Vibrance)*colorSat; 29 | c0.rgb = mix(vec3(dot(c0, CoefLuma)), c0.rgb, colorSat); 30 | return c0; 31 | } 32 | -------------------------------------------------------------------------------- /Effects/CrossHatch.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK OUTPUT 2 | //!BIND HOOKED 3 | //!DESC CrossHatch 4 | 5 | /* CrossHatch (style Effect for video content) 6 | A different effect is produced based on HOOK point: LUMA (colors) or OUTPUT/MAIN (Red + 2 grays + White) 7 | 8 | adapted to mpv .hook by butterw 9 | from https://github.com/pixijs/pixi-filters/blob/master/filters/cross-hatch/src/crosshatch.frag (MIT License) 10 | */ 11 | 12 | #define Hatch_mode 2 //default: 2 [0, 1, 2, 3] 13 | #define White vec4(245, 245, 245, 255)/255. 14 | 15 | vec4 hook(){ 16 | #define _hatch 1.25*pow(2, Hatch_mode) 17 | vec4 color = White; //Background Color 18 | float lum = length(HOOKED_texOff(0).rgb); //Gray 19 | 20 | float coords_sum = gl_FragCoord.x + gl_FragCoord.y; 21 | float coords_diff = gl_FragCoord.x - gl_FragCoord.y; 22 | 23 | 24 | if ((lum < 1.) && mod(coords_sum, _hatch) == 0.) // */* 25 | color = vec4(0.25); 26 | 27 | if ((lum < 0.75) && mod(coords_diff, _hatch) == 0.) // *\* 28 | color = vec4(1., 0, 0, 1); //Red 29 | 30 | if ((lum < 0.50) && mod(coords_sum -5, _hatch) == 0.) // */offset* 31 | color = vec4(0.5); 32 | 33 | if ((lum < 0.3) && mod(coords_diff -5, _hatch) == 0.0)// *\offset* 34 | color = vec4(0.5); 35 | return color; 36 | } 37 | -------------------------------------------------------------------------------- /Effects/Sepia.md: -------------------------------------------------------------------------------- 1 | ## Sepia and Tone Effects 2 | 3 | Sepia can designate a variety of different effects. The Sepia effects considered here have the following properties: 4 | - Tinted monochrome image with Blacks and Whites unchanged. 5 | - Brightness/saturation stay mostly the same. Details are preserved. 6 | - the Sepia tint can be brown, yellow, pink... 7 | - Tone Effects are like Sepia but use a different color tint (ex: Purple, Blue) 8 | 9 | ### Lightweight Shader approaches 10 | - (Color) >> Grayscale >> RGB x normalized_tint. This approach might be the most straightforward for customization (contrast, tint). It can also be used with a color Input rather than grayscale: midtone/hightlight greys are tinted pink. 11 | - RGB >> ColorMatrix >> Sepia 12 | - mpv: RGB >> lut shader >> Sepia 13 | 14 | ### Results 15 | Testing is done using colorbarsHD input 16 | 17 | - Grayscale(NoChroma) / mpv Lut-4(Sepia_Paint):
18 | 19 | 20 | - Colormatrix / Grayscale+ rgb normalized tint:
21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Effects/bCrossHatch.hlsl: -------------------------------------------------------------------------------- 1 | #define Hatch_mode 3. //default: 2 [0, 1, 2, 3] 2 | #define White float4(245, 245, 245, 255)/255. //Background Color 3 | 4 | /* 5 | CrossHatch (style Effect for video content) 6 | quad-colors: Red + 2 grays + White background 7 | 8 | bCrossHatch.hlsl by butterw (1 texture, 31 arithmetic) 9 | adapted from https://github.com/pixijs/pixi-filters/blob/master/filters/cross-hatch/src/crosshatch.frag (MIT License) 10 | 11 | */ 12 | 13 | 14 | 15 | sampler s0: register(s0); 16 | float2 p0: register(c0); // (Width, Height) 17 | #define _hatch 1.25*pow(2, Hatch_mode) 18 | 19 | float4 main(float2 tex: TEXCOORD0): COLOR { 20 | float4 color = White; 21 | float lum = length(tex2D(s0, tex)); //Gray 22 | 23 | float2 coords = floor(p0 * tex); 24 | float coords_sum = coords.x + coords.y; 25 | float coords_diff = coords.x - coords.y; 26 | 27 | if (lum < 1 && fmod(coords_sum, _hatch)==0) // */* 28 | color = 0.25; 29 | 30 | if (lum < 0.75 && fmod(coords_diff, _hatch)==0) // *\* 31 | color = float4(1., 0, 0, 1); //Red 32 | 33 | // if (lum < 0.50 && fmod(coords_sum-5, _hatch)==0) color = float4(0,1,0,1);// */offset* 34 | 35 | if (lum < 0.3 && fmod(coords_diff-5, _hatch)==0)// *\offset* 36 | color = 0.5; 37 | return color; 38 | } 39 | -------------------------------------------------------------------------------- /Effects/bStipple.hlsl: -------------------------------------------------------------------------------- 1 | /* bStipple, comic-book style effect 2 | use pre-resize 3 | can also handle low-res input 4 | 5 | Mod and .hook/hlsl port by butterw 6 | based on BlueNoiseStippling2 https://www.shadertoy.com/view/ldyXDd by FabriceNeyret2 7 | - perf: (5 texture, 45 arithmetic), without stipple: (5 texture, 13 arithmetic) !!! 8 | */ 9 | 10 | #define stepnoise0(pos, size) rnd( floor(pos/size)*size ) //float2 pos 11 | #define rnd(U) frac(sin(mul(U, 1e3*float2x2(1, -7.131, 12.9898, 1.233))) *43758.5453) 12 | 13 | // --- Stippling mask to cover up artifacts based on blue noise 14 | float stipple_mask(float2 pos) { 15 | #define SEED1 1.705 16 | #define DMUL 8.12235325 17 | pos+= stepnoise0(pos, 5.5)*DMUL -0.5*DMUL; 18 | float f = frac(pos.x*SEED1 +pos.y/(SEED1+0.15555)); 19 | f*= 1.002; 20 | return (pow(f, 150.) +1.3*f) *0.7/2.3; 21 | } 22 | 23 | sampler s0: register(s0); 24 | float2 p0: register(c0); //W, H 25 | float2 p1: register(c1); //px, py 26 | 27 | #define S 0.7 //default: 0.7, 0: bw output 28 | #define CoefLuma float4(.3, .6, .1, 0) 29 | #define get(uv) tex2D(s0, tex + p1*uv) 30 | 31 | float4 main(float2 tex: TEXCOORD0): COLOR { 32 | float4 c0 = tex2D(s0, tex); 33 | 34 | float4 blur; //smooth kernel: (+)4(1) 35 | blur = get(float2(0, -1)); 36 | blur+= get(float2(-1, 0)); 37 | blur+= get(float2(1, 0)); 38 | blur+= get(float2(0, 1)); 39 | float f = dot(26*c0-50*0.125*blur, CoefLuma); 40 | // return f; //Luma unsharp mask x50 (massively overshapened) 41 | 42 | /*-- Stippling --*/ 43 | float mask = stipple_mask(floor(p0 *tex));//0.25; 44 | f = step(mask, f); 45 | return lerp(f, c0, S); 46 | } 47 | -------------------------------------------------------------------------------- /Effects/dots.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK LUMA 2 | //!BIND HOOKED 3 | //!DESC dots 4 | 5 | #define Scale 0.45 //[0.3, 0.6] default: 0.4. Higher for smaller dots 6 | 7 | /* default hook: LUMA >> Luma Dots + Chroma 8 | Art/Style Effect for Video content 9 | 10 | adapted/mod by butterw from https://github.com/pixijs/pixi-filters/blob/master/filters/dot/src/dot.frag (MIT License) 11 | ...grayscale, mostly black and white version: OUTPUT+CHROMA hooks, can use 2instances. 12 | */ 13 | 14 | float pattern(){ 15 | #define Angle 5. 16 | float s = sin(Angle), c = cos(Angle); 17 | vec2 coord = HOOKED_pos * input_size; 18 | vec2 pt = Scale* vec2(dot(vec2(c, -s), coord), dot(vec2(s, c), coord)); 19 | vec2 sp = sin(pt); 20 | return 4 *sp.x *sp.y; 21 | } 22 | 23 | vec4 hook(){ 24 | float luma = HOOKED_texOff(0).r; 25 | return vec4(clamp(10*luma-5 + pattern(), 16/255., 245/255.)); // Clamped output 26 | // return vec4(10*luma-5 + pattern()); 27 | } 28 | 29 | //!HOOK NONE 30 | //!BIND HOOKED 31 | //!DESC NoChroma 32 | 33 | /* default hook: NONE, 34 | alt hook: CHROMA, zeroes out Chroma */ 35 | vec4 hook() { 36 | return vec4(0.5); //zeroes out Chroma: Luma Only 37 | } 38 | -------------------------------------------------------------------------------- /Effects/gr-Dots.hlsl: -------------------------------------------------------------------------------- 1 | #define Scale 0.4 //[0.3, 0.6] default: 0.4. Higher for smaller dots 2 | 3 | /* 4 | gr-Dots.hlsl (mpc-hc dx9 pixel shader) 5 | ported by butterw from https://github.com/pixijs/pixi-filters/blob/master/filters/dot/src/dot.frag (MIT License) 6 | 7 | Output is grayscale, mostly black and white 8 | Can be used Post-resize, can use 2instances. 9 | v0.1: (1 texture, 18 arithmetic) 10 | */ 11 | sampler s0: register(s0); 12 | float2 p0: register(c0); //W, H 13 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) // BT.709 & sRBG luma coef (Monitors, HDTV) 14 | 15 | float pattern(float2 tex){ 16 | #define Angle 5.0 //0: flat 17 | float s = sin(Angle), c = cos(Angle); 18 | float2 coord = tex * p0; 19 | float2 pt = Scale *float2(c*coord.x - s*coord.y, s*coord.x + c*coord.y); 20 | // return 4 *sin(pt.x) *sin(pt.y); 21 | float2 sp = sin(pt); 22 | return 4 *sp.x *sp.y; 23 | } 24 | 25 | float4 main(float2 tex: TEXCOORD0): COLOR { 26 | // return pattern(tex); //Show dot pattern 27 | float4 color = tex2D(s0, tex); 28 | float luma = dot(color, CoefLuma); 29 | luma = 10*luma-5 + pattern(tex); 30 | // return clamp(luma, 16/255., 245/255.); //clamp gray output: +2arithmetic 31 | return luma; 32 | } 33 | -------------------------------------------------------------------------------- /FilmGrain_Noise/FilmGrain1.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_2_0 2 | #define INTENSITY 0.05 3 | 4 | /* --- mpv FilmGrain v1 (dx9) --- */ 5 | /* v0.2 (2023-11) ported to mpc-hc by butterw, License: GPL v3 6 | (1 texture, 30 arithmetic) 7 | 8 | Additive Grayscale Noise. 9 | Analysis (from test screenshot): truncated gaussian/binomial. When used pre-resize with upscaling produces a clean gaussian histogram. 10 | 11 | parameter INTENSITY 12 | noise intensity, ex: 0.05, typ: [0 to 0.10]. 13 | 14 | original file: https://github.com/haasn/gentoo-conf/blob/xor/home/nand/.mpv/shaders/filmgrain.glsl 15 | Copyright (c) 2015 Niklas Haas 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | The above copyright notice and this permission notice shall be included in 23 | all copies or substantial portions of the Software. 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | --- 32 | 33 | Performance of available hlsl filmgrain and noise shaders. 34 | - bNoise0.hlsl: (1 texture, 12 arithmetic) 35 | - PS_Noise.hlsl mod: (1 texture, 29 arithmetic) 36 | - mpv FilmGrain.glsl port: (1 texture, 30 arithmetic) << this file 37 | - semi-random grayscale noise.hlsl by janwillem32 (NoiseStrength: 1/64.) i<4: (1 texture, 38 arithmetic) 38 | - SweetFx.FilmGrain.hlsl v1.0 4 parameters: (1 texture, 46 arithmetic) 39 | */ 40 | sampler s0: register(s0); 41 | float4 p0: register(c0); 42 | #define random frac(p0.w) //uses clock instead of random, mpv PRNG [0, 1.0] 43 | 44 | 45 | float permute(float x) { 46 | x*= (34*x + 1); 47 | return 289 *frac(x *1.0/289); 48 | } 49 | 50 | float rand(inout float state) { 51 | state = permute(state); 52 | return frac(state *1.0/41); 53 | } 54 | 55 | float4 main(float2 tex: TEXCOORD0): COLOR { 56 | float4 color = tex2D(s0, tex); 57 | 58 | float3 m = float3(tex, random) +1.; 59 | float state = permute(permute(m.x) + m.y) + m.z; 60 | 61 | float p = 0.95*rand(state) +0.025; 62 | float q = p - 0.5; 63 | float r = q * q; 64 | 65 | #define a0 0.151015505647689 66 | #define a1 -0.5303572634357367 67 | #define a2 1.365020122861334 68 | #define b0 0.132089632343748 69 | #define b1 -0.7607324991323768 70 | 71 | float grain = q* (a2 + (a1*r +a0)/(r*r + b1*r +b0)); 72 | grain*= 0.255121822830526; // normalize to [-1,1] 73 | 74 | // return 0.5 +5*INTENSITY*grain; //Show_Grain 75 | color.rgb+= INTENSITY*grain; 76 | return color; 77 | } 78 | -------------------------------------------------------------------------------- /FilmGrain_Noise/Readme_FilmGrain.md: -------------------------------------------------------------------------------- 1 | ## Noise/FilmGrain shaders 2 | 3 | Filmgrain (on a low intensity setting) improves perceptual quality of most compressed videos. In particular content with low or no noise, ex: the source noise may have been removed at encoding to improve compressibility. It may also help mask artifacts. 4 | 5 | The main reason not to use Filmgrain in mpc-hc/be was the performance hit on lower end systems. These new shaders offer a major speed improvement over previously available shaders without creating a visible noise pattern. 6 | 7 | Note: The Noise/Filmgrain shader should be run after any sharpening shader (to avoid sharpening the noise). 8 | Issue with mpc-hc/be EVR-CP: In fullscreen post-resize, the shader also gets applied to the black bars. This is not noticeable with normal noise intensities, however. 9 | These shaders use the Clock parameter available in mpc-hc/be (time in seconds since the program was launched) as randomization. 10 | 11 | ### Performance of available hlsl Noise & Filmgrain shaders. 12 | - bNoise.hlsl: (1 texture, 12 arithmetic) << new lightweight Shader. histogram is fairly clean for typical noise Strengths. Centering the histogram costs one extra operation. 13 | - PS_Noise.hlsl mod/optim: (1 texture, 18 arithmetic), non symetrical distribution 14 | - mpv Noise.glsl port: (1 texture, 27 arithmetic), quite noisy histogram 15 | - FilmGrain1.hlsl: port from mpv FilmGrain.glsl: (1 texture, 30 arithmetic), truncated gaussian lobe with a width of approx 4sigma. 16 | - semi-random grayscale noise.hlsl by janwillem32, i<4: (1 texture, 38 arithmetic). Clean gaussian histogram. Patterning present with less iterations ! 17 | - SweetFx.FilmGrain.hlsl v1.0: (1 texture, 46 arithmetic), 4 parameters, noise is multiplicative not additive, histogram not tested. 18 | 19 | Some limited quality testing was done based on the output noise histogram, but more feedback would be welcome. 20 | The noise histograms were obtained through screenshots (at 1080p), this doesn't allow for precise analysis of the time-dependant behaviour, especially around launch. 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /FilmGrain_Noise/bNoise.hlsl: -------------------------------------------------------------------------------- 1 | #define Strength 4. //ex: 16.0 2 | 3 | sampler s0: register(s0); 4 | float4 p0: register(c0); 5 | #define Clock p0.w 6 | 7 | /* bNoise.hlsl, cheap hlsl noise (1 texture, 12 arithmetic) 8 | tweaked by butterw from: https://www.shadertoy.com/view/4sXSWs posted by jcant0n (glsl) 9 | */ 10 | 11 | float4 main(float2 tex: TEXCOORD0): COLOR { 12 | float4 color = tex2D(s0, tex); 13 | float2 otex = 3*tex + 12; 14 | float x = otex.x * otex.y * 10*Clock; 15 | 16 | float4 noise = Strength*fmod((fmod(x, 13.0) + 1.0) *(fmod(x, 123.0) + 1.0), 0.01); //-0.005 17 | // return 10 *noise; //Noise output 18 | return color + noise; //color + noise; 19 | } 20 | -------------------------------------------------------------------------------- /FilmGrain_Noise/blank_color_ffmpeg_1080p_Gray128_10s.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/FilmGrain_Noise/blank_color_ffmpeg_1080p_Gray128_10s.mp4 -------------------------------------------------------------------------------- /FilmGrain_Noise/blank_color_ffmpeg_1080p_Gray128_rgb24_snapshot_00.05_[2020.10.19_20.57.46].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/FilmGrain_Noise/blank_color_ffmpeg_1080p_Gray128_rgb24_snapshot_00.05_[2020.10.19_20.57.46].png -------------------------------------------------------------------------------- /FilmGrain_Noise/dx11/grain.hlsl: -------------------------------------------------------------------------------- 1 | // $MinimumShaderProfile: ps_4_0 2 | #define Strength 16. 3 | #define Curve01 0.25 4 | #define Show_Grain 0 5 | 6 | /* --- grain (dx11) --- */ 7 | /* v1.01 (2023-11) released by butterw under GPLv3 8 | Gaussian noise generation is from "semi-random grayscale noise.hlsl", (C) 2011 Jan-Willem Krans (janwillem32 hotmail.com), license: GPLv2. 9 | (1 texture, 42 arithmetic) >> (1 texture, 38 arithmetic with Curve01:1). 10 | 11 | Filmgrain is a physical characteric of film media, digital camera sensors don't have grain, only noise. A small amount of grain paradoxically increases perceived sharpness and quality (ex: sources that have been denoised prior to encoding). But adding too much just degrades the signal-over-noise ratio. It is recommended to adjust the Strength down so the grain is barely visible. 12 | Grain shaders typically generate a dynamic luma noise pattern and blend it with the original image. Grain is calculated for each xy pixel of the image using a pseudo-random hash function with time and counter variables used as seed, leading to a dynamic grain pattern updated every frame. Additive grain blending does not significantly alter the original brightness and contrast of the image. 13 | This shader allows to apply less grain to dark and bright areas vs midtones by multiplying grain with a shaping function based on luma. The shaping function is a tunable parabola centered at midgray. The values in x:0 and x:1.0 are set by parameter Curve01. Grain should only be added after any sharpening operations are performed (sharpening generated grain is undesirable). 14 | 15 | out = c0.rgb + noiseStrength*grain 16 | with c0 and out pixel.rgb values in [0, 1.0]. 17 | and noiseStrength = 0.01*Strength. 18 | 19 | grain = gShape(luma, Curve01) *grain 20 | with grain, positive or negative grayscale value in [-0.125, 0.125], random variable with gaussian distribution. 21 | and gShape in [0, 1.0]. 22 | 23 | ## Parameters ## 24 | - Strength, percentage, ex: 16. [0 to 35.0], 0: no effect. 25 | - Curve01, curve shaping parameter, ex:0.25, typ [0 to 1.0], 1.0: uniform grain , 0: parabola(luma). 26 | gshape(luma:0) = gshape(luma:1.0) = Curve 27 | - Show_Grain, 0: default, [0 or 1] 1: display only the noise pattern. 28 | 29 | */ 30 | 31 | #define noiseStrength Strength*0.01 //apply Strength scaling factor. 32 | #define n 4 //number of randomization iterations, ex:4, ! a lower RunCount will cause patterned noise. 33 | #define PI acos(-1) //3.14159265 34 | const static float4 RandomFactors = {PI*PI*PI*PI, exp(5), pow(13, 0.5*PI), sqrt(1997) }; 35 | #define rnd(u) r_in.u = frac( dot(r_in, RandomFactors) ); 36 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 37 | #define pow2(u) (u)*(u) 38 | #define gshape(x) lerp(1 -pow2(2*x -1), 1, Curve01) // C + (1-C)*(1 -(2*x-1)^2) = 1 + (C-1)*(2*x-1)^2 //for negative C, use: max(gshape(luma), 0) 39 | 40 | Texture2D tex: register(t0); 41 | SamplerState samp: register(s0); 42 | cbuffer PS_CONSTANTS: register(b0) { 43 | float px; 44 | float py; 45 | float2 wh; 46 | uint counter; 47 | float clock; 48 | }; 49 | 50 | float4 main(float4 pos: SV_POSITION, float2 coord: TEXCOORD): SV_Target { 51 | float2 seed = 1.0/65536 *float2(counter, clock) + exp(5); 52 | float4 r_in = float4( coord.xy, seed); 53 | for(int i=0; i< n; i++) { rnd(x) rnd(y) rnd(z) rnd(w) }; // randomize 54 | float grain; 55 | #if Show_Grain == 1 56 | grain = 0.25 -dot(r_in, 0.125); //in [-0.125, 0.125] 57 | return 0.5 + grain; 58 | #endif 59 | grain = 0.25*noiseStrength -dot(r_in, 0.125*noiseStrength); // noiseStrength*grain 60 | float4 c0 = tex.Sample(samp, coord); 61 | float luma = dot(c0, CoefLuma); 62 | grain = gshape(luma)*grain; 63 | return c0 + grain; 64 | } 65 | -------------------------------------------------------------------------------- /FilmGrain_Noise/grain-profile_parabola_linear_uniform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/FilmGrain_Noise/grain-profile_parabola_linear_uniform.png -------------------------------------------------------------------------------- /FilmGrain_Noise/grain.35_D1vs.30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/FilmGrain_Noise/grain.35_D1vs.30.png -------------------------------------------------------------------------------- /FilmGrain_Noise/grain_densityCurve-vsLuma_D0-black_D1-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/FilmGrain_Noise/grain_densityCurve-vsLuma_D0-black_D1-red.png -------------------------------------------------------------------------------- /MPC-HC_Shaders-Menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/MPC-HC_Shaders-Menu.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bShaders 2 | Effects/Filters for video playback 3 | This project aims at providing shaders (DirectX .hlsl or mpv .hook glsl files), tools and comparison screenshots for realtime video Effects. The focus is on best implementation (and tuned parameter settings) of lightweight gpu shaders. 4 | 5 | Shaders tested on MPC-HC video player (EVR-CP Dx9) on integrated graphics. https://www.videohelp.com/software/Media-Player-Classic-Home-Cinema 6 | MPC-HC enables hardware-accelerated playback of local and internet videos without requiring the installation of additional codecs. 7 | 8 | Mpv is an open-source cross-platform video player: https://mpv.io/installation/ 9 | how to use shaders in mpv: https://forum.doom9.org/showthread.php?p=1926639#post1926639 10 | 11 | Effects: 12 | - Pixelate (Mosaic) 13 | - Edge detection (in Luma): Sobel, Prewitt, Frei-Chen 14 | - FilmGrain/Noise (bNoise.hlsl lightweight additive noise pixel shader and others) 15 | 16 | Blur: 17 | - Single-pass gSmooth (Gaussian Blur 3x3, hw.3) 18 | - Multi-pass (Gaussian 7-tap, hw.5, hw.9, quarter-frame hw.9, Kawase, Dual-Kawase, BoxBlur(3x) with adjustable size) 19 | - Blurred pillarbox borders (fill_bb.avs avisynth script) 20 | 21 | Art/Style Effect for Video content (vs Film): 22 | - Dots 23 | - CrossHatch 24 | - bStipple comic book style 25 | - bSobel_Edge: grayscale Sobel Edge detection + saturated color to achieve a cartoon effect 26 | 27 | Tools: 28 | - barMask (Custom Border Masks + frame shift) 29 | ...Quadri-Frame 2x2 visualization, ex: ROGB or separate grayscale RYGB components 30 | - bStrobe (Time-based Effect) 31 | - test_linearSampling (test whether Hardware Linear Sampling (hw) is working in player/gpu-driver): 32 | ...it works in mpv but not in mpc-hc/be ! 33 | - test_LimitedRange (limited range tools using Avisynth and ffmpeg) 34 | ...bHighL.hlsl (out-of-range pixel highlighting) 35 | 36 | Mpv: 37 | - NoChroma.hook (Grayscale source shader) 38 | - simple examples for embedded textures and compute shaders 39 | 40 | See also my shader gists: https://gist.github.com/butterw 41 | 42 | --- 43 | basic intro about hlsl/glsl pixel shaders here: 44 | https://forum.videohelp.com/threads/397797-Pixel-shaders-for-video-playback-%28-hlsl%29 45 | 46 | Unofficial video player shaders guide: https://forum.doom9.org/showthread.php?t=181584 47 | 48 | ![](./assets/Posterize.vs.Posterize2_8-b.png) 49 | -------------------------------------------------------------------------------- /assets/Pixelate1_100_1080p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/Pixelate1_100_1080p.png -------------------------------------------------------------------------------- /assets/Posterize.vs.Posterize2_8-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/Posterize.vs.Posterize2_8-b.png -------------------------------------------------------------------------------- /assets/Sobel_Sat_Color_x1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/Sobel_Sat_Color_x1280.jpg -------------------------------------------------------------------------------- /assets/Y_map4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/Y_map4.jpg -------------------------------------------------------------------------------- /assets/bHatch_6levels_4col_pop_x1280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/bHatch_6levels_4col_pop_x1280.png -------------------------------------------------------------------------------- /assets/bPosterize2-4_rgb_x1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/bPosterize2-4_rgb_x1280.jpg -------------------------------------------------------------------------------- /assets/img/ColorBarsHD720_Colormatrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/ColorBarsHD720_Colormatrix.png -------------------------------------------------------------------------------- /assets/img/ColorBarsHD720_Sepia_Paint-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/ColorBarsHD720_Sepia_Paint-4.png -------------------------------------------------------------------------------- /assets/img/ColorBarsHD720_noChroma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/ColorBarsHD720_noChroma.png -------------------------------------------------------------------------------- /assets/img/ColorBarsHD720_rgb-nTint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/ColorBarsHD720_rgb-nTint.png -------------------------------------------------------------------------------- /assets/img/adm-bSegments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/adm-bSegments.png -------------------------------------------------------------------------------- /assets/img/mp-hc_HideWindowedControls.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/mp-hc_HideWindowedControls.jpg -------------------------------------------------------------------------------- /assets/img/mpc-be_minimal_flybar_seekbar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/mpc-be_minimal_flybar_seekbar.jpg -------------------------------------------------------------------------------- /assets/img/mpc-hc_O_Keys_Shader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/mpc-hc_O_Keys_Shader.png -------------------------------------------------------------------------------- /assets/img/mpvnet_menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/mpvnet_menu.jpg -------------------------------------------------------------------------------- /assets/img/scr_A-Pack v1.40 - video Adjustments shaders.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/img/scr_A-Pack v1.40 - video Adjustments shaders.jpg -------------------------------------------------------------------------------- /assets/mpv_LSobel.inv.dk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/mpv_LSobel.inv.dk.jpg -------------------------------------------------------------------------------- /assets/mpv_bStipple_x1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/mpv_bStipple_x1280.jpg -------------------------------------------------------------------------------- /assets/mpv_freichen_x1280_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/mpv_freichen_x1280_grey.png -------------------------------------------------------------------------------- /assets/mpv_invSobel_Luma_noThreshold.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/mpv_invSobel_Luma_noThreshold.jpg -------------------------------------------------------------------------------- /assets/original_exterior_49.05_x1280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/original_exterior_49.05_x1280.png -------------------------------------------------------------------------------- /assets/pencil-sketch_EdgeSharpen_x1280_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/pencil-sketch_EdgeSharpen_x1280_grey.png -------------------------------------------------------------------------------- /assets/rgb_luma-map4_0.25color.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/rgb_luma-map4_0.25color.jpg -------------------------------------------------------------------------------- /assets/vlc_gradient-edge-cartoon_720p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/assets/vlc_gradient-edge-cartoon_720p.png -------------------------------------------------------------------------------- /bPixelate.hlsl: -------------------------------------------------------------------------------- 1 | /*--- User Settings ---*/ 2 | #define PixelateMode 2 // methods [1, 2, 3] use Npixels, [11, 12, 13] use TargetSize, def: 2 3 | #define Npixels 100. // >=1 Number of output "Pixels" in the largest dimension, def: 100 4 | #define TargetSize 50 // >=2 Output Pixel target size 5 | 6 | 7 | /*--- bPixelate.hlsl, v1.0 by butterw 2020-06-23 --- 8 | Pre-Resize shader, tested in Mpc-hc video player v1.9.3 (renderer: EVR-CP) 9 | 10 | Pixelation is the effect observed when you aggressively downscale resolution (to TargetSize) then resize back up the rounded Npixels. 11 | Works for different source resolutions, aspect ratios. The effect achieved depends on the zoom of the scene. 12 | Can be used as an intro/transition effect (DePixelation or Pixelation/depixelation). Has a retro low-res appeal. 13 | Square pixels can be more appealing vs rectangular pixels, especially for low npixels values, but require more arithmetic operations. 14 | */ 15 | 16 | sampler s0: register(s0); 17 | float2 p0: register(c0); 18 | #define W p0.x // Image Width 19 | #define H p0.y // Height 20 | #define Green float4(0, 1, 0, 0) 21 | 22 | /* --- Pixelate(tex, npixels) --- 23 | npixels>1.: the number of pixels in the largest dimension 24 | a wide range of values is possible, ex: Npixels: [1, 400], TargetSize: [2, 100] 25 | 26 | - to achieve a fixed TargetSize vs input resolution: Pixelate(tex, max(W, H)/TargetSize) 27 | */ 28 | float4 Pixelate1(float2 tex, float npixels){ 29 | /* rectangular pixels. 30 | simplest/fastest version (1texture, 4arithmetic) 31 | */ 32 | return tex2D(s0, floor(tex*npixels)/npixels); 33 | } 34 | 35 | float4 Pixelate2(float2 tex, float npixels){ 36 | /* with square pixels, (1texture, 11arithmetic) */ 37 | float pixelSize = max(W, H)/npixels; 38 | return tex2D(s0, floor(tex*p0/pixelSize)*pixelSize/p0); 39 | } 40 | 41 | float4 Pixelate3(float2 tex, int npixels){ 42 | /* with square pixels and offset, int npixels>1 43 | (1texture, 22arithmetic), test: 1280x720, n=7, n=45 44 | */ 45 | int pixelSize = max(W, H)/npixels; 46 | float2 dpixel = pixelSize-(p0 %pixelSize)/2.; 47 | return tex2D(s0, floor((p0*tex+dpixel)/pixelSize) *pixelSize/p0); 48 | } 49 | 50 | 51 | float4 main(float2 tex: TEXCOORD0): COLOR { 52 | #if PixelateMode == 1 53 | return Pixelate1(tex, Npixels); 54 | #elif PixelateMode == 2 55 | return Pixelate2(tex, Npixels); 56 | #elif PixelateMode == 3 57 | return Pixelate3(tex, Npixels); 58 | #endif 59 | 60 | float npixels = max(W, H)/TargetSize; 61 | #if PixelateMode == 11 62 | return Pixelate1(tex, npixels); 63 | #elif PixelateMode == 12 64 | return Pixelate2(tex, npixels); 65 | #elif PixelateMode == 13 66 | return Pixelate3(tex, npixels); 67 | #endif 68 | 69 | return Green; 70 | } -------------------------------------------------------------------------------- /bStrobe.hlsl: -------------------------------------------------------------------------------- 1 | /* --- Parameters --- 2 | Timings, float>=0 in seconds 3 | Color, rgba float4 [0, 1] 4 | */ 5 | #define Tfirst 3. //10. // Time of the first run 6 | #define Tcycle 10. //4. // Repetition period. 0: No repetition. 7 | #define Td 2. // Duration. 0: deactivates the effect. 8 | #define ScreenColor float4(16., 16., 16., 0)/255 //rgba [0, 1.] 9 | #define End -2//-2 //26.5 10 | /* 0: no End Condition (default) 11 | >0: End time in seconds ex: 26.5 12 | <0: a max number of runs of the Effect, ex -2: the effect will run twice. 13 | 14 | */ 15 | 16 | /* --- bStrobe.hlsl --- v1.0 by butterw 17 | Ready to use time-configurable color frame Effect. 18 | Parameters: ScreenColor, Time of first run (Tfirst), Duration (Td), Repetition period (Tcycle), End (Number of runs, End time or No End). 19 | timings specified in seconds, or in video frames if you replace Clock by Counter (untested). 20 | 21 | Tested in mpc-hc v1.9.3: 22 | - Opening the player by double clicking a video starts Clock 23 | - Note that Opening another video or doing Pause/Stop does not reset Clock 24 | 25 | performance: (1 texture, 11 arithmetic). 26 | smooth_Strobe: with 1s fade-in 27 | */ 28 | 29 | 30 | 31 | /* --- Global Constants --- */ 32 | sampler s0: register(s0); 33 | float4 p0: register(c0); 34 | // #define Counter p0.z //float frame counter, starting at 0. 35 | #define Clock p0.w //in s, starting at 0., updated every frame 36 | 37 | 38 | float4 Strobe(float4 inputColor) { 39 | /* returns the provided input color: Placeholder for any effect/glitch */ 40 | return inputColor; 41 | } 42 | 43 | float4 smooth_Strobe(float4 pixcolor, float tstart) { 44 | /* blending (t_sm=1 second) between the pixel color and ScreenColor */ 45 | return lerp(pixcolor, ScreenColor, saturate(Clock-tstart)); // blend: 1/t_sm *(Clock-tstart) 46 | } 47 | 48 | float4 main(float2 tex: TEXCOORD0): COLOR { 49 | float4 c0 = tex2D(s0, tex); 50 | 51 | int nRuns = (Tcycle>0) ? trunc(max((Clock - Tfirst), 0)/Tcycle): 0; //Run Counter >=0 (limitation: no persistent variables!) 52 | if ((End>0 && Clock>End) || (End<0 && nRuns+1>(-End))) return c0; //End Condition 53 | 54 | float tstart = Tfirst + nRuns*Tcycle; 55 | if (Clock>=tstart && Clock> blurGauss_pass2 (vert. pass) 8 | Mode=1 uses a separable Gaussian Kernel, without hw linear sampling optimization 9 | default Kernel 7-tap Gaussian, sigma=1.5. A different sigma/Kernel K can be selected in the code. 10 | 11 | 12 | tested in mpc-hc v1.9.8.38 13 | - hw linear sampling (modes 2, 3, 4) doesn't work as expected (uses nearest neighbor sampling instead) !!! 14 | - loading _pass1.hlsl now automatically loads _pass2.hlsl. 15 | 16 | you can run the the 2-pass shader multiple times to achieve a stronger blur (ex: 3 times) 17 | 1=Blur Gaussian (3x) 18 | PreResize1=.\blurGauss_pass1.hlsl;.\blurGauss_pass1.hlsl;.\blurGauss_pass1.hlsl 19 | 20 | Separable Gaussian Kernel with linear sampling (9-tap filter approx.) 21 | http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ 22 | 23 | */ 24 | sampler s0: register(s0); 25 | float2 p1: register(c1); 26 | 27 | #if Mode==1 //gBlur7 (7 texture, 11 arithmetic) per pass 28 | // http://dev.theomader.com/gaussian-kernel-calculator/ 29 | //#define K float4(0.324225, 0.233638, 0.087348, 0.016901) //sigma=1.2 30 | #define K float4(0.266346, 0.215007, 0.113085, 0.038735) //sigma=1.5 (default) 31 | //#define K float4(0.230781, 0.198557, 0.126451, 0.059602) //sigma=1.8 32 | #elif Mode==2 //hw.blur5 (3 texture, 6 arithmetic, 5 with tex +p1.x*float2(-Offsets[i], 0)) 33 | #define Offsets float2(0.0, 4/3.) 34 | #define K float2(0.29411764705882354, 0.35294117647058826) 35 | #elif Mode==3 //hw.blur9 (5 texture, 8 arithmetic) 36 | #define Offsets float3(0.0, 1.3846153846, 3.2307692308) 37 | #define K float3(0.2270270270, 0.3162162162, 0.0702702703) 38 | #elif Mode==4 //hw.blur13 39 | #define Offsets float4(0.0, 1.411764705882353, 3.2941176470588234, 5.176470588235294) 40 | #define K float4(0.1964825501511404, 0.2969069646728344, 0.09447039785044732, 0.010381362401148057) 41 | #endif 42 | 43 | /* --- Main --- */ 44 | float4 main(float2 tex: TEXCOORD0): COLOR { //(7 texture, 11 arithmetic) 45 | float4 c0 = K[0] *tex2D(s0, tex); 46 | #if Mode==1 47 | c0+= K[1] *tex2D(s0, tex + float2( p1.x, 0)); 48 | c0+= K[1] *tex2D(s0, tex + float2( -p1.x, 0)); 49 | c0+= K[2] *tex2D(s0, tex + float2( 2*p1.x, 0)); 50 | c0+= K[2] *tex2D(s0, tex + float2(-2*p1.x, 0)); 51 | c0+= K[3] *tex2D(s0, tex + float2( 3*p1.x, 0)); 52 | c0+= K[3] *tex2D(s0, tex + float2(-3*p1.x, 0)); 53 | 54 | #elif Mode >1 55 | [unroll] for (int i=1; i < Mode; i++) { 56 | c0+= tex2D(s0, tex +p1.x*float2(Offsets[i], 0)) *K[i]; 57 | c0+= tex2D(s0, tex -p1.x*float2(Offsets[i], 0)) *K[i]; 58 | } 59 | #endif 60 | return c0; 61 | } -------------------------------------------------------------------------------- /blur/blurGauss_pass2.hlsl: -------------------------------------------------------------------------------- 1 | #define Mode 1 2 | 3 | /* blurGauss_pass2: Gaussian blur (Vertical Pass) 4 | Second pass of 2-pass shader, please ensure the 2 passes use the same parameters/Mode. 5 | 6 | by butterw, License: GPL v3 7 | */ 8 | 9 | sampler s0: register(s0); 10 | float2 p1: register(c1); 11 | 12 | #if Mode==1 //gBlur7, http://dev.theomader.com/gaussian-kernel-calculator/ 13 | //#define K float4(0.324225, 0.233638, 0.087348, 0.016901) //sigma=1.2 14 | #define K float4(0.266346, 0.215007, 0.113085, 0.038735) //sigma=1.5 (default) 15 | //#define K float4(0.230781, 0.198557, 0.126451, 0.059602) //sigma=1.8 16 | #elif Mode==2 17 | #define Offsets float2(0.0, 4/3.) //(3 texture, 6 arithmetic) 18 | #define K float2(0.29411764705882354, 0.35294117647058826) 19 | #elif Mode==3 20 | #define Offsets float3(0.0, 1.3846153846, 3.2307692308) 21 | #define K float3(0.2270270270, 0.3162162162, 0.0702702703) 22 | #elif Mode==4 23 | #define Offsets float4(0.0, 1.411764705882353, 3.2941176470588234, 5.176470588235294) 24 | #define K float4(0.1964825501511404, 0.2969069646728344, 0.09447039785044732, 0.010381362401148057) 25 | #endif 26 | 27 | /* --- Main --- */ 28 | float4 main(float2 tex: TEXCOORD0): COLOR { //(7 texture, 11 arithmetic) 29 | float4 c0 = K[0] *tex2D(s0, tex); 30 | #if Mode==1 //(7 texture, 11 arithmetic) 31 | c0+= K[1] *tex2D(s0, tex +float2(0, p1.y)); 32 | c0+= K[1] *tex2D(s0, tex +float2(0, -p1.y)); 33 | c0+= K[2] *tex2D(s0, tex +p1*float2(0, 2)); 34 | c0+= K[2] *tex2D(s0, tex -p1*float2(0, 2)); 35 | c0+= K[3] *tex2D(s0, tex +p1*float2(0, 3)); 36 | c0+= K[3] *tex2D(s0, tex -p1*float2(0, 3)); 37 | #elif Mode >1 38 | [unroll] for (int i=1; i < Mode; i++) { 39 | c0+= tex2D(s0, tex + p1.y*float2(0, Offsets[i])) *K[i]; 40 | c0+= tex2D(s0, tex - p1.y*float2(0, Offsets[i])) *K[i]; 41 | } 42 | #endif 43 | return c0; 44 | } -------------------------------------------------------------------------------- /blur/fill_bb.avs: -------------------------------------------------------------------------------- 1 | /* fill_bb.avs, a Realtime customizable Avisynth(+) script to remove/fill Black Bars 2 | fullscreen Black Bars are the consequence of the source video having a different Aspect ratio from the screen, they are also sometimes added to the source at encoding. 3 | 4 | by butterw, tested in mpc-hc, mpc-be, mpv video players 5 | v0.1: added audio 6 | 7 | All steps are optional: 8 | - crop video to Aspect Ratio, or in pixels 9 | - scale video (up to max_zoom) 10 | - fullscreen pad with solid color 11 | - OR background: fullscreen image 12 | - OR background: live-blurred 13 | - fullscreen overlay(background, vid) 14 | 15 | variable names: 16 | - src: source video 17 | - bg: background video 18 | - vid: output video 19 | 20 | ## Requires external plugins: */ 21 | # LoadPlugin("c:\Program Files (x86)\AviSynth+\plugins64+\LSMASHSource.dll") 22 | # blurred background also requires: FastBlur.dll, AddGrainC.dll (see FrostyBorders for a dedicated encoding script) 23 | 24 | ## Output Screen Resolution: 25 | global Ws = 1920 26 | global Hs = 1080 27 | 28 | 29 | function scale(clip v, int "max_zoom"){ 30 | /* scale clip to fullscreen or if specified to max_zoom. No crop-zoom */ 31 | max_zoom = default(max_zoom, 1000) 32 | s_factor = min(min(Ws*1.0/v.Width, Hs*1.0/v.Height), max_zoom) 33 | w = int(v.Width *s_factor)/2 *2 34 | h = int(v.Height*s_factor)/2 *2 35 | Spline36Resize(v, w, h) 36 | } 37 | 38 | function padc(clip v, int targetW, int targetH, int "bgColor"){ 39 | /* center pad clip with bgColor */ 40 | bgColor = default(bgColor, 0) #rgb $FF0000, named preset color_darkblue, 41 | wx = (targetW - v.Width)/4 *2 42 | wy = (targetH - v.Height)/4 *2 43 | AddBorders(v, wx, wy, wx, wy, bgColor) #all borders must be mod2 44 | } 45 | 46 | 47 | ##--- Load the Source ---## 48 | /* Load the source video (mp4/mov file) */ 49 | fname = "b:\Videos\monster-2_ed.mp4" 50 | src = LSmashVideoSource(fname, prefer_hw=3) 51 | audio = LSmashAudioSource(fname) 52 | 53 | 54 | /* Crop the source to Aspect Ratio 55 | OR with mod-2 values in pixels src.Crop(left, top, -right, -bottom) 56 | */ 57 | # cropAR = 1.31 58 | # cropL = int(0.5*(src.Width -src.Height*cropAR))/2*2 59 | # src = src.Crop(CropL, 0, -CropL, 0) 60 | 61 | /* Scale Video to max_zoom (no crop-zoom) */ 62 | vid = scale(src, max_zoom=10) 63 | 64 | ##--- Process the Background ---## 65 | 66 | /* Pad Video (centered) with solid color 67 | ex: $a0a0a0 (grey160), $7f6065 68 | */ 69 | vid = padc(vid, Ws, Hs, $a0a0a0) 70 | 71 | /* OR Load an image to use as background: 72 | image should have fullscreen resolution, you can resize it if required */ 73 | # fname = "b:\unfocus_dk_1080p.png" 74 | # bg = ImageSource(fname, 0, src.FrameCount-1) 75 | 76 | /*-- OR Live Blurred Background, requires plugins: FastBlur, AddGrainC 77 | to improve performance downscale the source before bluring: either to 256x256 or to half-resolution 78 | recommended resizer bspline (smooth cubic): BicubicResize(w, h, b=1, c=0) 79 | dither and noise are used to hide the resulting artifacts 80 | */ 81 | w = 256 82 | h = w 83 | 84 | ## Alternative Downscale resolution: 85 | # k = 4 86 | # w = src.Width/k *2 87 | # h = src.Height/k *2 88 | 89 | # bg = src.BicubicResize(w, h, b=1, c=0).ColorYUV(gain_y=-30).FastBlur(8, iterations=3, dither=yes).BicubicResize(Ws, Hs, b=1, c=0).AddGrain(var=2.0) 90 | 91 | 92 | /* Output: Centered Overlay (Video over background) */ 93 | # Last = vid 94 | # vid = Overlay(bg, Last, x=(bg.Width-Width)/4 *2, y=(bg.Height-Height)/4 *2) 95 | return AudioDub(vid, audio) 96 | -------------------------------------------------------------------------------- /blur/gSmooth.hook.glsl: -------------------------------------------------------------------------------- 1 | /* Gaussian Smoothing filter (3x3 or 5x5 kernel), hw: uses hw linear sampling 2 | by butterw, License: GPL v3 3 | 4 | Select the HOOKs you want to apply (ex: MAIN, OUTPUT), NONE disables: 5 | blurring should be performed pre-upscaling for maximum effect (use MAIN) 6 | - hw.gSmooth3: default, 3x3 Gaussian kernel using hw linear sampling (4 texture fetches) 7 | - gSmooth3: 3x3 Gaussian kernel, full (9 texture fetches) 8 | - hw.gSmooth5: 2-pass 5x5 Gaussian kernel using hw linear sampling (2*3 texture fetches) 9 | For stronger blurs use blurGaussR.hook (hw.Gaussian9x9 downscaled by 2) and blurGauss.hook (hw.Gaussian9x9) for subsequent passes. 10 | */ 11 | 12 | //!HOOK MAIN 13 | //!BIND HOOKED 14 | //!DESC hw.gSmooth3 15 | 16 | vec4 hook(){ //hw.gSmooth3 (3x3 gaussian kernel) using hw linear sampling, tex:4 17 | vec4 blur = HOOKED_texOff(vec2(-0.5, -0.5)); 18 | blur+= HOOKED_texOff(vec2(-0.5, 0.5)); 19 | blur+= HOOKED_texOff(vec2(0.5, -0.5)); 20 | blur+= HOOKED_texOff(vec2(0.5, 0.5)); 21 | return blur*0.25; 22 | } 23 | /*--------------------------------------------------------------- */ 24 | 25 | //!HOOK NONE_MAIN 26 | //!BIND HOOKED 27 | //!DESC gSmooth3 28 | 29 | /* Gaussian 3x3 Kernel: 30 | sigma=0.85, in multi-pass sigma=sigma*sqrt(2) 31 | [ 1 , 2 , 1 ] 32 | [ 2 , 4 , 2 ] 33 | [ 1 , 2 , 1 ] 34 | */ 35 | 36 | vec4 hook(){ //gSmooth3 (3x3 gaussian kernel), tex:9 37 | if (HOOKED_pos.x<0.5) return HOOKED_texOff(0); 38 | vec4 blur = HOOKED_texOff(-1); 39 | blur+= 2*HOOKED_texOff(ivec2(0, -1)); 40 | blur+= HOOKED_texOff(ivec2(1, -1)); 41 | blur+= 2*HOOKED_texOff(ivec2(-1, 0)); 42 | blur+= 4*HOOKED_texOff(0); 43 | blur+= 2*HOOKED_texOff(ivec2(1, 0)); 44 | blur+= HOOKED_texOff(ivec2(-1, 1)); 45 | blur+= 2*HOOKED_texOff(ivec2(0, 1)); 46 | blur+= HOOKED_texOff(1); 47 | return blur/16.; 48 | } 49 | 50 | /*--------------------------------------------------------------- */ 51 | 52 | //!HOOK NONE_MAIN 53 | //!BIND HOOKED 54 | //!DESC hw.gSmooth5 55 | 56 | vec4 hook() { //H-pass, 5x5 gaussian kernel, 2pass with hw linear sampling 57 | vec4 color = HOOKED_tex(HOOKED_pos) *0.29411764705882354; 58 | color+= HOOKED_tex(HOOKED_pos +vec2( 4/3., 0)*HOOKED_pt) *0.35294117647058826; 59 | color+= HOOKED_tex(HOOKED_pos +vec2(-4/3., 0)*HOOKED_pt) *0.35294117647058826; 60 | return color; 61 | } 62 | 63 | //!HOOK NONE_MAIN 64 | //!BIND HOOKED 65 | //!DESC hw.gSmooth5_Y 66 | 67 | vec4 hook() { //V-pass, 5x5 gaussian kernel, 2pass with hw linear sampling 68 | vec4 color = HOOKED_tex(HOOKED_pos) *0.29411764705882354; 69 | color+= HOOKED_tex(HOOKED_pos +vec2(0, 4/3.)*HOOKED_pt) *0.35294117647058826; 70 | color+= HOOKED_tex(HOOKED_pos +vec2(0, -4/3.)*HOOKED_pt) *0.35294117647058826; 71 | return color; 72 | } 73 | -------------------------------------------------------------------------------- /blurDKawase14.hlsl: -------------------------------------------------------------------------------- 1 | /* Dual-Kawase blur - First and Second Passes of 4 (pre-resize shader) 2 | 3 | tested-hc on mpc-hc v1.9.6, by butterw (5 texture, 9 arithmetic) 4 | use: 5 | 1=Blur Dual-Kawase 6 | PreResize1=.\blurDKawase14.hlsl;blurDKawase14.hlsl;blurDKawase34.hlsl;blurDKawase34.hlsl 7 | 8 | */ 9 | 10 | sampler s0: register(s0); 11 | float2 p1: register(c1); 12 | #define offset 3. 13 | /* --- Main --- */ 14 | float4 main(float2 tex: TEXCOORD0): COLOR { // downsample pass-1 & pass-2 15 | float2 uv = 2*tex; //downsize by 2 16 | 17 | float4 sum = 4.*tex2D(s0, uv); 18 | sum += tex2D(s0, uv - p1 *offset); 19 | sum += tex2D(s0, uv + p1 *offset); 20 | sum += tex2D(s0, uv + float2(p1.x, -p1.y) *offset); 21 | sum += tex2D(s0, uv - float2(p1.x, -p1.y) *offset); 22 | 23 | return 0.125*sum; 24 | } -------------------------------------------------------------------------------- /blurDKawase34.hlsl: -------------------------------------------------------------------------------- 1 | /* Dual-Kawase blur - Passes 3 and 4 (resize-up blur) 2 | tested-hc on mpc-hc v1.9.6, by butterw (8 texture, 18 arithmetic) 3 | 4 | dual filtering kawase method described in GDC2015 by Marius Bjorge, also used by KDE 5 | 6 | Dn: (5 texture, 9 arithmetic)*2 7 | Up: (8 texture, 18 arithmetic)*2 8 | 9 | */ 10 | 11 | sampler s0: register(s0); 12 | float2 p1: register(c1); 13 | #define offset 3. 14 | 15 | /* --- Main --- */ 16 | float4 main(float2 tex: TEXCOORD0): COLOR { // upsample pass-1 & pass-2 17 | float2 uv = 0.5*tex; //resize-up x2 18 | float2 halfpixel = 0.25*p1; 19 | 20 | float4 sum = tex2D(s0, uv + float2(-halfpixel.x *2, 0) *offset); 21 | sum += tex2D(s0, uv + float2(-halfpixel.x, halfpixel.y) *offset) *2.; 22 | sum += tex2D(s0, uv + float2(0, halfpixel.y *2) *offset); 23 | sum += tex2D(s0, uv + halfpixel *offset) *2.; 24 | sum += tex2D(s0, uv + float2(halfpixel.x *2, 0) *offset); 25 | sum += tex2D(s0, uv + float2(halfpixel.x, -halfpixel.y) *offset) *2.; 26 | sum += tex2D(s0, uv + float2(0, -halfpixel.y *2) *offset); 27 | sum += tex2D(s0, uv + float2(-halfpixel.x, -halfpixel.y) *offset) *2.; 28 | 29 | return sum/12.; 30 | } 31 | -------------------------------------------------------------------------------- /blurKawase_15.hlsl: -------------------------------------------------------------------------------- 1 | /* Kawase blur - First of Five Passes (pre-resize shader) 2 | tested-hc on mpc-hc v1.9.6, by butterw (4 texture, 7 arithmetic) 3 | 4 | 5-pass Kawase blur with kernel offsets {0.5, 1.5, 2.5, 2.5, 3.5} matches output of a 35x35 Gaussian kernel ? 5 | https://software.intel.com/content/www/us/en/develop/blogs/an-investigation-of-fast-real-time-gpu-based-image-blur-algorithms.html 6 | */ 7 | 8 | #define i 0.5 //kernel offsets for 5-pass Kawase blur {0.5, 1.5, 2.5, 2.5, 3.5} 9 | 10 | 11 | sampler s0: register(s0); 12 | float2 p1: register(c1); 13 | 14 | /* --- Main --- */ 15 | float4 main(float2 tex: TEXCOORD0): COLOR { 16 | float4 col; 17 | 18 | col = tex2D(s0, tex + p1*float2(i, i)); 19 | col+= tex2D(s0, tex + p1*float2(i, -i)); 20 | col+= tex2D(s0, tex + p1*float2(-i, i)); 21 | col+= tex2D(s0, tex + p1*float2(-i, -i)); 22 | 23 | return col/4.; 24 | } -------------------------------------------------------------------------------- /bw.hlsl: -------------------------------------------------------------------------------- 1 | #define Mode 2 //[1, 2, 3, 4] 2 | 3 | /* bw.hlsl: "Black&White" shader by butterw v0.1, RGB to grayscale conversion 4 | Mode 1: CoefLuma, sRGB grayscale 5 | Mode 2: CoefMonochrome, custom grayscale effect 6 | Mode 3: Equal Weight 7 | Mode 4: BrightnessMap Visualization with 4 levels. 8 | */ 9 | 10 | /* --- Grayscale Conversion Coefs --- 11 | 12 | float4(1/3., 1/3., 1/3., 0) //Equal weight 13 | float4(0.299, 0.587, 0.114, 0) ## mpc-hc Grayscale 14 | 15 | Some values for black&white film from SweetFx.Monochrome by CeeJay.dk: 16 | float4(0.18, 0.41, 0.41, 0) //Agfa 200X (default for Mode 2) 17 | float4(0.25, 0.39, 0.36, 0) //Agfapan 25 18 | float4(0.21, 0.40, 0.39, 0) //Agfapan 100 19 | float4(0.20, 0.41, 0.39, 0) //Agfapan 400 20 | float4(0.21, 0.42, 0.37, 0) //Ilford Delta 100 21 | float4(0.22, 0.42, 0.36, 0) //Ilford Delta 400 22 | float4(0.31, 0.36, 0.33, 0) //Ilford Delta 400 Pro & 3200 23 | float4(0.28, 0.41, 0.31, 0) //Ilford FP4 24 | float4(0.23, 0.37, 0.40, 0) //Ilford HP5 25 | float4(0.33, 0.36, 0.31, 0) //Ilford Pan F 26 | float4(0.36, 0.31, 0.33, 0) //Ilford SFX 27 | float4(0.21, 0.42, 0.37, 0) //Ilford XP2 Super 28 | float4(0.24, 0.37, 0.39, 0) //Kodak Tmax 100 29 | float4(0.27, 0.36, 0.37, 0) //Kodak Tmax 400 30 | float4(0.25, 0.35, 0.40, 0) //Kodak Tri-X 31 | */ 32 | #define CoefMonochrome float4(0.18, 0.41, 0.41, 0) //Agfa 200X 33 | #define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 34 | 35 | sampler s0: register(s0); 36 | 37 | float brightnessMap(float4 colorInput){ 38 | float lum = dot(colorInput, float4(0.299, 0.587, 0.114, 0)); // map function calculated from (R, G, B) 39 | /* Output colors: C0 is the darkest color, C3 is the lightest */ 40 | #define C3 0.95 41 | #define C2 0.7 42 | #define C1 0.45 43 | #define C0 0.1 44 | lum = (lum>0.8) ? C3: (lum>0.6) ? C2: (lum>0.2) ? C1: C0; 45 | return lum; 46 | } 47 | 48 | float4 main(float2 tex: TEXCOORD0): COLOR { 49 | float4 c0 = tex2D(s0, tex); //Color 50 | 51 | #if Mode==1 //sRGB Luma 52 | return dot(c0, CoefLuma); 53 | #elif Mode==2 54 | return dot(c0, CoefMonochrome); 55 | #elif Mode==3 56 | return dot(c0.rgb, 1/3.); 57 | #else // Mode==4: brightnessMap 58 | return brightnessMap(c0); 59 | #endif 60 | } 61 | -------------------------------------------------------------------------------- /edge/Sobel_Edge.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK CHROMA 2 | //!BIND HOOKED 3 | //!DESC NoChroma 4 | 5 | vec4 hook() {return vec4(0.5);} //enforces grayscale on yuv source 6 | 7 | /* luma Sobel_Edge(Threshold T_Sobel ex: 0.15-0.3) 8 | v0.5 by butterw 9 | 10 | HOOK points: 11 | - CHROMA:NoChroma 12 | - if no resize: (LUMA:hw.gSmooth3) > LUMA:Sobel_Edge 13 | - if upscaling: (LUMA:hw.gSmooth3) > OUTPUT:Sobel_Edge 14 | Smoothing may not be necessary, especially if a smooth scaler is in use (Mitchell-Netravali(1/3., 1/3.), BSpline(1, 0)). 15 | 16 | default output is Dark on White_limit background. 17 | set the threshold to achieve good detection. 18 | */ 19 | 20 | //!HOOK LUMA 21 | //!BIND HOOKED 22 | //!DESC hw.gSmooth3 23 | 24 | #define texo(uv) HOOKED_texOff(uv).r 25 | vec4 hook(){ //hw.gSmooth3 (3x3 gaussian kernel) using hw linear sampling, tex:4 26 | #define po 0.5 27 | float blur; 28 | blur = texo(vec2(-po, -po)); 29 | blur+= texo(vec2(-po, po)); 30 | blur+= texo(vec2( po, -po)); 31 | blur+= texo(vec2( po, po)); 32 | return vec4(blur*0.25); 33 | } 34 | 35 | //!HOOK NONE LUMA 36 | //!BIND HOOKED 37 | //!DESC Sobel_Edge 38 | 39 | #define T_Sobel 0.15 //Threshold: higher means less detection on screen 40 | 41 | #define texo(uv) HOOKED_texOff(uv).r 42 | vec4 hook(){ //8 tex 43 | float c8 = texo(1); 44 | c8-= texo(-1); 45 | float c3 = texo(vec2( 1,-1)); 46 | c3-= texo(vec2(-1, 1)); 47 | float c5 = texo(vec2( 1, 0)); 48 | c5-= texo(vec2(-1, 0)); 49 | vec2 g; 50 | g.x = c8 +c3 +2*c5; 51 | c8-= c3; 52 | float c7 = texo(vec2(0, 1)); 53 | c7-= texo(vec2(0,-1)); 54 | g.y = c8 +2*c7; 55 | float edge = length(g); 56 | 57 | #define White_limit 180/255. // <1. to avoid bright white 58 | // return (edge>T_Sobel) ? vec4(min(edge, White_limit)): vec4(0); 59 | return (edgeT_Sobel) ? vec4(edge): vec4(0); 88 | // return (edge>T_Sobel) ? vec4(min(edge, White_limit)): vec4(0); 89 | return (edge1:over-saturated 31 | 32 | fname = "b:\Video.mp4" 33 | src = LSmashVideoSource(fname, prefer_hw=3) 34 | /*-------------------------------------------------------*/ 35 | 36 | 37 | if (Mode==3){ ## Canny.bw 38 | vid = src.TCannyMod(mode=0, sigma=1.0, sobel=true, t_l=60, t_h=60, chroma=3) ## 3. Canny(Y) 39 | } 40 | else if (Mode==1 || Mode==10){ 41 | vid = src.TCannyMod(mode=1, sigma=0.5, sobel=true, chroma=2) ##10. Sobel(Y) + UV 42 | if (Mode==1){ vid = vid.ColorYUV(off_u=5, off_v=12.8) } ##1. offset_uv tint 43 | } 44 | else if (Mode==20 || Mode==21){ 45 | vid = src.TCannyMod(mode=1, sigma=0.5, sobel=true, chroma=3) ##20. Sobel(Y).gray 46 | if (Mode==21){ vid = vid.mt_binarize(threshold=T_Sobel*255.0) } ##21. Sobel(Y).bw 47 | } 48 | else { ## (Mode==2) 49 | vid = src.TCannyMod(mode=1, sigma=0.5, sobel=true, chroma=3) ##20. Sobel(Y).gray 50 | src = src.Tweak(sat=Sat) 51 | ms = vid.mt_binarize(threshold=T_Sobel*255.0) 52 | vid = src.mt_merge(ms.Invert("Y"), ms, luma=true) ##black edges 53 | # vid = src.mt_merge(vid.tweak(bright=-192), ms, luma=true) ##dark edges 54 | return vid 55 | } 56 | vid = vid.Invert("Y") 57 | return vid 58 | -------------------------------------------------------------------------------- /edge/bSobel_Edge.hlsl: -------------------------------------------------------------------------------- 1 | #define T_Sobel 0.15 //Threshold: higher means less detection 2 | #define Mode 1 //[0, 1, 2] Default 1: Inverted Sobel, 0: Sobel, 2: Cartoon 3 | #define WhiteLimit 180/255. // <1. clamp output to avoid bright white 4 | #define SatFactor 1.8 //2.43 //0: gray, 1: no change, >1: Saturated Colors 5 | 6 | /* --- bSobel_Edge by butterw v1.31 7 | Sobel Edge Detection in Luma (3x3 kernel) with adjustable Threshold 8 | tested in mpc-hc (8 texture, 25 arithmetic) 9 | 10 | Use with high-res input or post-upscale. 11 | 12 | Changelog v1.3: 13 | - added Inverted Mode (Dark lines on WhiteLimit background) 14 | - added Cartoon Mode (Dark Edges + Saturated Color) 15 | --- */ 16 | 17 | sampler s0: register(s0); 18 | float2 p1: register(c1); 19 | #define px p1.x 20 | #define py p1.y 21 | #define CoefLuma float4(0.212656, 0.715158, 0.072186, 0) // BT.709 & sRBG luma coef (HDTV, SDR Monitors) 22 | 23 | float4 Sobel_Edge(float2 tex){ 24 | float4 c8 = tex2D(s0, tex +p1); 25 | c8-= tex2D(s0, tex -p1); 26 | float4 c3 = tex2D(s0, tex +float2( px, -py)); 27 | c3-= tex2D(s0, tex +float2(-px, py)); 28 | float4 c4 = tex2D(s0, tex +float2(-px, 0)); 29 | float4 c5 = tex2D(s0, tex +float2( px, 0)); 30 | float2 g; 31 | g.x = dot(c8 + c3 -2*c4 + 2*c5, CoefLuma); 32 | float4 c7 = tex2D(s0, tex +float2(0, py)); 33 | float4 c2 = tex2D(s0, tex +float2(0, -py)); 34 | g.y = dot(c8 -c3 + 2*c7 -2*c2, CoefLuma); 35 | float edge = length(g); 36 | 37 | #if Mode == 0 //Sobel 38 | return (edge>T_Sobel) ? min(edge, WhiteLimit): 0; 39 | #elif Mode == 1 //Inverted_Sobel: dark grey on white background 40 | return (edge1:Saturated ex:2.43 6 | 7 | /* A lightweight rgb saturation/desaturation shader for mpv 8 | v0.1 by butterw 9 | hook: MAIN, OUTPUT 10 | */ 11 | 12 | vec4 hook(){ 13 | vec4 c0 = HOOKED_texOff(0); 14 | float gray = dot(c0, vec4(1/3., 1/3., 1/3., 0)); 15 | return mix(vec4(gray), c0, SatFactor); 16 | } -------------------------------------------------------------------------------- /mpv/bShadows_next.hook: -------------------------------------------------------------------------------- 1 | //!PARAM shadows 2 | //!DESC Darkens the shadows (negative) 3 | //!TYPE CONSTANT float 4 | //!MINIMUM -0.5 5 | -0.15 6 | 7 | //!PARAM mode 8 | //!DESC 0: default, -1: red, 8: c0+Shadows*(1-luma)**8 9 | //!TYPE DEFINE 10 | 4 11 | 12 | //!HOOK MAIN 13 | //!BIND HOOKED 14 | //!DESC bShadows_next 15 | 16 | /* --- bShadows_next (mpv .hook, gpu-next) --- */ 17 | /* 18 | Example of a mpv custom-shaders with tunable parameters (req. vo=gpu-next) 19 | see: https://libplacebo.org/custom-shaders/#param-name 20 | 21 | use: 22 | with default values: > mpv --vo=gpu-next --glsl-shaders=s/bShadows_next.hook; video1.mp4 23 | parameter shadows=0.10 > mpv --vo=gpu-next --glsl-shaders=s/bShadows_next.hook; --glsl-shader-opts=Shadows=0.10,mode=8 video1.mp4 24 | ! Parameter names are case-sensitive 25 | 26 | */ 27 | 28 | /* v1.20 (2023-06) released by butterw under GPLv3 29 | (1 texture, 5 arithmetic) 30 | 31 | Darken or lighten the shadows. 32 | 33 | c0 = c0 + Shadows*(1-luma)**4 34 | with c0: pixel.rgb in [0, 1.0] 35 | 36 | - shadows Parameter, 0: no change, 37 | negative: darkens the shadows, ex: -0.15 38 | positive: lighten the shadows 39 | 40 | - mode Parameter, 41 | 4: (1-luma)**4, default, -1: All red, 8: (1-luma)**8 42 | 43 | */ 44 | 45 | #define LumaCoef vec4(0.2126, 0.7152, 0.0722, 0) 46 | 47 | vec4 hook() { 48 | vec4 c0 = HOOKED_texOff(0); 49 | float shadowsBleed = 1.0 -dot(c0, LumaCoef); 50 | shadowsBleed *=shadowsBleed; 51 | shadowsBleed *=shadowsBleed; 52 | #if mode == 8 53 | shadowsBleed *=shadowsBleed; //tryout: (1-luma)**8 54 | #elif mode == -1 55 | return vec4(1, 0, 0, 0); //test: red screen 56 | #endif 57 | return c0 + shadows *shadowsBleed; 58 | } -------------------------------------------------------------------------------- /mpv/bSide.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC bSide 4 | 5 | /* bSide.hook by butterw v0.1 6 | hook: MAIN, OUTPUT, LUMA, NATIVE 7 | Apply different effects to different parts of the screen. 8 | 9 | Input is typically a single video file. To display multiple video files use ffmpeg (or avisynth) as input, ex: 10 | mpv --lavfi-complex="[vid1][vid2]hstack[vo]" "b:\Videos\file1.mp4" --external-file="b:\Videos\file2.mp4" 11 | goal is typically for comparison purpose: No Effect (O) vs. Shader 12 | OR to simultaneously display 4 different image channels/effects (ex: ROGB) 13 | 14 | Input >> Shader Output: 15 | Splitscreen: A | B 16 | Side-by-side: A0| A1 17 | >> can also be applied to vertical splitscreen 18 | 19 | Quad display (2x2), ex: 20 | .r Original 21 | .g .b 22 | */ 23 | 24 | #define pos HOOKED_pos 25 | vec4 fx(vec4 color){ //example effect 26 | return 1-color; //invert 27 | } 28 | 29 | vec4 hook() { 30 | vec4 color = HOOKED_tex(pos); 31 | 32 | /* Select desired output: */ 33 | #if 1 //2x2 channel display, ex rO-gb 34 | vec4 c1 = HOOKED_tex(2*pos -step(0.5, pos)); 35 | if (pos.x<0.5) c1 = (pos.y<0.5) ? vec4(c1.r): vec4(c1.g); 36 | else c1 = (pos.y<0.5) ? c1: vec4(c1.b); 37 | return c1; 38 | #elif 0 //side-by-side: fx(R)| R 39 | if (pos.x<0.5) return HOOKED_tex(pos+vec2(0.5, 0)); 40 | return fx(color); 41 | #else 42 | // if (pos.x<0.5) return color; // Splitscreen: O | fx 43 | if (pos.y<0.5) return color; //Vertical splitscreen 44 | return fx(color); 45 | #endif 46 | } 47 | -------------------------------------------------------------------------------- /mpv/bw.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC Black&White 4 | 5 | #define CoefMonochrome vec4(0.18, 0.41, 0.41, 0) 6 | 7 | /* custom RGB grayscale conversion v0.1 8 | shader tested on mpv v0.33 by butterw 9 | 10 | vec4(0.18, 0.41, 0.41, 0) //Agfa 200X from SweetFx.Monochrome 11 | vec4(1/3., 1/3., 1/3., 0) //Equal weight 12 | vec4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV Luma 13 | */ 14 | 15 | vec4 hook(){ 16 | vec4 c0 = HOOKED_texOff(0); 17 | return vec4(dot(c0, CoefMonochrome)); 18 | } -------------------------------------------------------------------------------- /mpv/cs_wkgroups.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK OUTPUT //hook: LUMA, MAIN, OUTPUT 2 | //!BIND HOOKED 3 | //!COMPUTE 32 32 //Workgroup bloc size(X, Y) is defined as X*Y threads, with 1 thread per input pixel. 4 | //!DESC Compute_WorkGroups 5 | 6 | /* mpv .hook Compute Shader example by butterw 7 | COMPUTE bw bh [tw th] 8 | 9 | Compute Shaders have a slightly different syntax vs fragment shaders. They don't return a pixel color value, output is done through out_image. 10 | 11 | Threads have integer IDs: 12 | uvec3:*/ 13 | #define NumWkg gl_NumWorkGroups 14 | #define WkgSize gl_WorkGroupSize 15 | #define WkgID gl_WorkGroupID 16 | #define LoID gl_LocalInvocationID // gl_LocalInvocationID.xy * gl_WorkGroupID.xy == gl_GlobalInvocationID 17 | #define GlobID gl_GlobalInvocationID 18 | 19 | #define LoIndex gl_LocalInvocationIndex //uint 20 | 21 | 22 | #define Orange vec4(1, .5, 0, 1) 23 | #define Blue vec4(0 ,.5, 1, 1) 24 | 25 | void hook() { //executed per thread, in WorkGroup blocks 26 | vec4 color = HOOKED_tex(HOOKED_pos); //Read input texel 27 | 28 | if (WkgID.x==frame && WkgID.x==WkgID.y) color = Blue; // effect at mpv first-launch 29 | if (WkgID.x==2 && WkgID.y==0) color = Orange; 30 | 31 | ivec2 coords = ivec2(GlobID); //Global (x, y) ID for pixel threads ex: (100, 240) 32 | imageStore(out_image, coords, color); 33 | } 34 | -------------------------------------------------------------------------------- /mpv/lut/Readme.md: -------------------------------------------------------------------------------- 1 | ## Lut Shaders 2 | 3 | CLUTs (Color Look-Up-Tables) are widely used in for color-grading and applying color effects (ex: film emulation). 4 | Many luts are available on the internet: 5 | - https://gmic.eu/color_presets/ 6 | - https://filterhunt.com/ 7 | 8 | Mpv video player can apply text-based lut transformations through ffmpeg --vf:
9 | ! use a relative path with / for the lut file. Input is converted to rgb24.
10 | mpv --vf=lut3d=clut.cube video.mp4
11 | However, this is quite cpu intensive at higher resolutions/framerates, so a shader gpu-based approach is preferable. 12 | 13 | ### MPV Lut Shaders 14 | Mpv allows embedded (1D or 3D) textures in shaders, which can be used for fast LUT transformations.
15 | For Color Luts, RGB 3D textures with 3D linear interpolation can be used.
16 | ! The texture format (FBO) must be supported by the gpu driver, which can be an issue cross-platform for floating point formats (vs more lightweight rgba8 format which is simple to encode and widely supported).
17 | The required conversion from the available Lut formats to .hook hex-texture can be done through a Python script (I'm using Open-CV and Numpy for this).
18 | ! As mentionned in https://developer.nvidia.com/gpugems/gpugems2/part-iii-high-quality-rendering/chapter-24-using-lookup-tables-accelerate-color, a lookup coordinate correction is required in the shader to avoid crushed blacks, ex for cube-4 identity lut:
19 | return texture(CLUT, 0.75*color.rgb + 0.125); //lutSize: 4
20 | correction applied: (lutSize - 1.0)/lutSize *oldCoord + 1.0/(2.0 *lutSize) 21 | 22 | ### Main Clut formats 23 | * Haldclut square .png image (24 or 48bit rgb), ex: hald level 8, 512x512 image (equivalent to cube-64: 64x64x64 colors) 24 | * Adobe .cube, text based format with floating point r g b values, typ in the [0, 1.0] range. 25 | 26 | The cube corresponds to a flattened (line-by-line) haldclut image.
27 | Filesize for cube-64: 200KB for haldclut png, 1MB for uncompressed rgb32, 2MB for .hook and 7MB for .cube ! 28 | 29 | #### Identity Image 30 | * hald-2-identity_8x8_cube4.png (8bit haldclut level-2 identity png image, 8x8 pixels, equivalent to a 4x4x4 rgb cube):
31 | 32 | 33 | By using an identity image of the desired size as input in a graphics program, the output corresponds to the transformation lut (which can then be saved as a png image).
34 | When an identity lut transformation is applied, the output should theoretically be the same as the input. 35 | 36 | #### ImageMagick (IM) 37 | The command line image processing program ImageMagick can be useful for haldcluts.
38 | * convert hald:8 id-8_512x512_cube64.png //generate a level 8 haldclut identity image 39 | * convert rose.png lut_sepia.png -hald-clut rose_sepia.png //apply the haldclut lut_sepia.png on the input image and save the output 40 | * magick cube:bw-4.cube[2] bw-4.png //convert .cube lut to an haldclut level 2 (64x64) .png 41 | -------------------------------------------------------------------------------- /mpv/lut/bw-4.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!BIND CLUT 4 | //!DESC bw-4 rollei_ortho_25 5 | 6 | /* this is a contrasted Black & White Shader. Alternatives would be: 7 | for less contrast: 8 | - NoChroma (cancels source chroma) 9 | - bw (Agfa 200X) 10 | 11 | Higher contrasts for Blacks or Whites are possible, but not suited for all sources. 12 | - Kodachrome; bw 13 | - etc. 14 | see: https://gmic.eu/color_presets/bw_sample_7.html#browse 15 | */ 16 | 17 | 18 | vec4 hook(){ 19 | vec4 color = HOOKED_texOff(0); 20 | return texture(CLUT, 0.75*color.rgb +0.125); 21 | } 22 | 23 | //created with butterw/lut2hook.py from BW_rollei_ortho_25 smooth https://filterhunt.com/showLut/AkbY2lGABCA 24 | //!TEXTURE CLUT 25 | //!SIZE 4 4 4 26 | //!FORMAT rgba8 27 | //!FILTER LINEAR 28 | 000000aa000000aa010101aa020202aa272727aa282828aa2B2B2Baa2D2D2Daa696969aa6A6A6Aaa6C6C6Caa6F6F6FaaCCCCCCaaCCCCCCaaCDCDCDaaCFCFCFaa292929aa2C2C2Caa2F2F2Faa323232aa515151aa545454aa575757aa5B5B5Baa8E8E8Eaa909090aa939393aa969696aaD9D9D9aaD9D9D9aaDADADAaaDCDCDCaa6E6E6Eaa737373aa787878aa7D7D7Daa9D9D9DaaA0A0A0aaA4A4A4aaA9A9A9aaCACACAaaCBCBCBaaCDCDCDaaD0D0D0aaEEEEEEaaEEEEEEaaF0F0F0aaF1F2F2aaC7C7C7aaCBCBCBaaCECECEaaD1D1D1aaDDDDDDaaDFDFDFaaE1E1E1aaE3E3E3aaF2F2F2aaF3F3F3aaF6F6F6aaF9F9F9aaFFFFFFaaFFFFFFaaFFFFFFaaFFFFFFaa 29 | -------------------------------------------------------------------------------- /mpv/lut/clut_id4.hook: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!BIND CLUT 4 | //!DESC CLut Identity-4 5 | 6 | /* a 4x4x4 rgb identity lut shader for mpv by butterw (v0.1) 7 | this is an example of a 3D color look-up-table (CLUT) shader in mpv: the interpolated output of this shader should match the input (useful for testing purposes only !). 8 | https://developer.nvidia.com/gpugems/gpugems2/part-iii-high-quality-rendering/chapter-24-using-lookup-tables-accelerate-color 9 | */ 10 | 11 | vec4 hook(){ 12 | vec4 color = HOOKED_texOff(0); 13 | // return texture(CLUT, color.rgb); //without correction increases contrast 14 | return texture(CLUT, 0.75*color.rgb + 0.125); // coord correction: (lutSize - 1.0)/lutSize x oldCoord + 1.0/(2.0 x lutSize) 15 | } 16 | 17 | //created with butterw/lut2hook.py from id-4.cube 18 | //!TEXTURE CLUT 19 | //!SIZE 4 4 4 20 | //!FORMAT rgba8 21 | //!FILTER LINEAR 22 | 000000aa550000aaAA0000aaFF0000aa005500aa555500aaAA5500aaFF5500aa00AA00aa55AA00aaAAAA00aaFFAA00aa00FF00aa55FF00aaAAFF00aaFFFF00aa000055aa550055aaAA0055aaFF0055aa005555aa555555aaAA5555aaFF5555aa00AA55aa55AA55aaAAAA55aaFFAA55aa00FF55aa55FF55aaAAFF55aaFFFF55aa0000AAaa5500AAaaAA00AAaaFF00AAaa0055AAaa5555AAaaAA55AAaaFF55AAaa00AAAAaa55AAAAaaAAAAAAaaFFAAAAaa00FFAAaa55FFAAaaAAFFAAaaFFFFAAaa0000FFaa5500FFaaAA00FFaaFF00FFaa0055FFaa5555FFaaAA55FFaaFF55FFaa00AAFFaa55AAFFaaAAAAFFaaFFAAFFaa00FFFFaa55FFFFaaAAFFFFaaFFFFFFaa 23 | -------------------------------------------------------------------------------- /mpv/lut/hald-2-identity_8x8_cube4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/lut/hald-2-identity_8x8_cube4.png -------------------------------------------------------------------------------- /mpv/lut/hald-2-identity_8x8_cube4.ppm: -------------------------------------------------------------------------------- 1 | P3 2 | 8 8 3 | 255 4 | 0 0 0 85 0 0 170 0 0 255 0 0 0 85 0 85 85 0 170 85 0 255 85 0 0 170 0 85 170 0 170 170 0 255 170 0 0 255 0 85 255 0 170 255 0 255 255 0 0 0 85 85 0 85 170 0 85 255 0 85 0 85 85 85 85 85 170 85 85 255 85 85 0 170 85 85 170 85 170 170 85 255 170 85 0 255 85 85 255 85 170 255 85 255 255 85 0 0 170 85 0 170 170 0 170 255 0 170 0 85 170 85 85 170 170 85 170 255 85 170 0 170 170 85 170 170 170 170 170 255 170 170 0 255 170 85 255 170 170 255 170 255 255 170 0 0 255 85 0 255 170 0 255 255 0 255 0 85 255 85 85 255 170 85 255 255 85 255 0 170 255 85 170 255 170 170 255 255 170 255 0 255 255 85 255 255 170 255 255 255 255 255 -------------------------------------------------------------------------------- /mpv/lut/id-4.cube: -------------------------------------------------------------------------------- 1 | LUT_3D_SIZE 4 2 | DOMAIN_MIN 0.0 0.0 0.0 3 | DOMAIN_MAX 1.0 1.0 1.0 4 | 0.000000 0.000000 0.000000 5 | 0.333333 0.000000 0.000000 6 | 0.666667 0.000000 0.000000 7 | 1.000000 0.000000 0.000000 8 | 0.000000 0.333333 0.000000 9 | 0.333333 0.333333 0.000000 10 | 0.666667 0.333333 0.000000 11 | 1.000000 0.333333 0.000000 12 | 0.000000 0.666667 0.000000 13 | 0.333333 0.666667 0.000000 14 | 0.666667 0.666667 0.000000 15 | 1.000000 0.666667 0.000000 16 | 0.000000 1.000000 0.000000 17 | 0.333333 1.000000 0.000000 18 | 0.666667 1.000000 0.000000 19 | 1.000000 1.000000 0.000000 20 | 0.000000 0.000000 0.333333 21 | 0.333333 0.000000 0.333333 22 | 0.666667 0.000000 0.333333 23 | 1.000000 0.000000 0.333333 24 | 0.000000 0.333333 0.333333 25 | 0.333333 0.333333 0.333333 26 | 0.666667 0.333333 0.333333 27 | 1.000000 0.333333 0.333333 28 | 0.000000 0.666667 0.333333 29 | 0.333333 0.666667 0.333333 30 | 0.666667 0.666667 0.333333 31 | 1.000000 0.666667 0.333333 32 | 0.000000 1.000000 0.333333 33 | 0.333333 1.000000 0.333333 34 | 0.666667 1.000000 0.333333 35 | 1.000000 1.000000 0.333333 36 | 0.000000 0.000000 0.666667 37 | 0.333333 0.000000 0.666667 38 | 0.666667 0.000000 0.666667 39 | 1.000000 0.000000 0.666667 40 | 0.000000 0.333333 0.666667 41 | 0.333333 0.333333 0.666667 42 | 0.666667 0.333333 0.666667 43 | 1.000000 0.333333 0.666667 44 | 0.000000 0.666667 0.666667 45 | 0.333333 0.666667 0.666667 46 | 0.666667 0.666667 0.666667 47 | 1.000000 0.666667 0.666667 48 | 0.000000 1.000000 0.666667 49 | 0.333333 1.000000 0.666667 50 | 0.666667 1.000000 0.666667 51 | 1.000000 1.000000 0.666667 52 | 0.000000 0.000000 1.000000 53 | 0.333333 0.000000 1.000000 54 | 0.666667 0.000000 1.000000 55 | 1.000000 0.000000 1.000000 56 | 0.000000 0.333333 1.000000 57 | 0.333333 0.333333 1.000000 58 | 0.666667 0.333333 1.000000 59 | 1.000000 0.333333 1.000000 60 | 0.000000 0.666667 1.000000 61 | 0.333333 0.666667 1.000000 62 | 0.666667 0.666667 1.000000 63 | 1.000000 0.666667 1.000000 64 | 0.000000 1.000000 1.000000 65 | 0.333333 1.000000 1.000000 66 | 0.666667 1.000000 1.000000 67 | 1.000000 1.000000 1.000000 68 | -------------------------------------------------------------------------------- /mpv/lut/id-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/lut/id-9.png -------------------------------------------------------------------------------- /mpv/lut/sepia_paint-4.hook.glsl: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!BIND CLUT 4 | //!DESC Sepia_Paint-4 5 | 6 | /* small RGB 3D-LUT (cube-4: 64 values) based on the Sepia filter of Paint.net 7 | This is a tone effect, the effect is the same if applied to a color image or the Y-only noChroma image. 8 | */ 9 | 10 | vec4 hook(){ 11 | vec4 color = HOOKED_texOff(0); 12 | return texture(CLUT, 3.0/4*color.rgb +1/8.0); 13 | } 14 | 15 | //created with butterw/lut2hook.py from sepia_paint-4.png 16 | //!TEXTURE CLUT 17 | //!SIZE 4 4 4 18 | //!FORMAT rgba8 19 | //!FILTER LINEAR 20 | 000000aa27190Faa453224aa604C3Baa443123aa5F4B3Aaa786452aa917E6Daa776351aa907D6CaaA69686aaBDB0A3aaA59585aaBCAFA2aaD1C8BEaaE6E1DBaa110904aa342317aa503C2Caa695544aa4F3B2Caa695544aa826E5Caa998776aa816D5Baa988675aaAFA091aaC5B9ADaaAE9F90aaC4B8ACaaDAD2CAaaEEEBE7aa1F130Baa3E2C1Eaa5A4636aa735F4Daa594535aa725E4Caa8B7867aaA29181aa8A7766aaA19080aaB8AA9CaaCDC3B8aaB7A99BaaCCC2B7aaE1DBD4aaF6F5F3aa2C1D12aa493627aa634F3Eaa7D6957aa624E3Daa7C6856aa938170aaAB9B8Caa92806FaaAA9A8BaaC0B3A6aaD6CDC4aaBFB2A5aaD5CCC3aaE9E5E0aaFFFFFFaa -------------------------------------------------------------------------------- /mpv/portable_config/mpv.conf: -------------------------------------------------------------------------------- 1 | # mpv configuration file: portable_config\mpv.conf 2 | # 2023-12 tested with mpv 0.37 on Win10 by butterw 3 | 4 | --no-input-default-bindings #define all keybindings in portable_config\mpv.conf 5 | # autoload-files=no #default: yes, automatically load/select external files (cover art, audio, sub). 6 | 7 | #--- Window -------- 8 | # --no-border 9 | --idle 10 | --force-window 11 | --keep-open =yes #no, yes: do not close the window just pause 12 | --no-hidpi-window-scale 13 | #--fullscreen #--fs 14 | #--autofit=1280x720 #50%x50% # max initial window size (specified either in pixels or as a screen %), no change to the aspect ratio. 15 | 16 | #--- intel uhd730 integrated gpu -------- 17 | --hwdec =d3d11va # 18 | --vo =gpu-next # default: gpu 19 | hdr-compute-peak=no 20 | # dither-depth =auto #default: auto. no: disables dithering. 8: 8bit. 21 | 22 | #--- Scalers -------- 23 | scale =lanczos #spline36 24 | cscale =catmull_rom #bilinear 25 | #dscale = mitchell #hermite 26 | linear-downscaling=yes 27 | 28 | #--- Shaders -------- 29 | # --gpu-shader-cache-dir=C:\Temp\mpv-shadercache 30 | --glsl-shaders="" 31 | 32 | ## Screenshots 33 | # --screenshot-dir="." 34 | screenshot-format=png #default: jpg 35 | screenshot-jpeg-quality=96 36 | 37 | #--- watch-later -------- 38 | --write-filename-in-watch-later-config 39 | --watch-later-options-append=glsl-shaders 40 | 41 | #--- OSD msg -------- 42 | --title ="${!glsl-shaders==:${?glsl-shaders:°}}${?pause==yes:|| }${?media-title:${media-title}}${!media-title:No file}${!playlist-count==1:${!playlist-count==0:°, ${playlist-pos-1}/${playlist-count}}}" 43 | # --osd-playing-msg 44 | # --term-playing-msg 45 | --term-status-msg="${?pause==yes:(Pause)} ${?=aid==1:A}${?=vid==1:V} ${playback-time} / ${duration} (${percent-pos:}%)${!glsl-shaders==: °${glsl-shaders:}}" 46 | # --osd-msg1 47 | --osd-msg2 = "${video-format} ${video-params/dw:}x${video-params/dh:}" #h264 1280x720 48 | --osd-msg3 ="(${percent-pos}%) ${playback-time}" #"${playback-time} / ${duration}" 49 | 50 | #--- OSD Prefs -------- 51 | --osd-duration =2000# Hide OSD text after (default: 1000)ms 52 | --osd-scale-by-window = no 53 | --osd-on-seek =msg-bar # bar msg: osd-msg3 54 | # osd-font = "SEGOE UI" #44 (default: sans-serif >> Arial) 55 | osd-font-size =44 # default: 55.0 56 | --osd-color =1.0/0.93/0.93/0.97 57 | osd-shadow-offset = 0 58 | --osd-margin-x=10 59 | --osd-margin-y=10 60 | osd-back-color ="#e6202020" 61 | osd-border-color ="#ff000000" # ignored when --osd-back-color is specified (and not set to completely transparent). 62 | osd-border-size =0 # default: 3.0 63 | # osd-bar = yes 64 | osd-bar-align-y=1.0 65 | osd-bar-w=100 66 | osd-bar-h=0.3 #if you need chapter markers, you could use something like: --osd-bar-h=1.0 --osd-bar-border-size=0.25 67 | osd-bar-border-size=0 68 | 69 | #--- Scripts -------- 70 | --no-osc 71 | # script-opts-add=osc-visibility=never # auto 72 | # script-opts-add=osc-showwindowed=no 73 | # --no-ytdl 74 | # script-opts-append=ytdl_hook-all_formats=yes 75 | # --load-osd-console=no 76 | # load-stats-overlay=no 77 | # --no-load-scripts # don't auto-load /scripts 78 | 79 | #--- Profiles -------- 80 | # --load-auto-profiles=no #auto 81 | -------------------------------------------------------------------------------- /mpv/portable_config/script-opts/btime.conf: -------------------------------------------------------------------------------- 1 | # [script-opts/btime.conf v0.30] 2 | # format=btime time format: playback-time / duration 3 | format=btime 4 | 5 | # alt=no alternative format: - remaining-time / duration 6 | alt=no 7 | 8 | # percent=no percent progress format: (percent-pos%) time-pos, OR with alt: -remaining-time (percent-pos%) 9 | percent=no 10 | 11 | # seek=yes display on seek event, yes: you need to turn-off the standard time message. 12 | seek=yes 13 | 14 | # ms=-1 <-1, value> duration of OSD display in milliseconds, ex: 1500, -1: standard OSD duration 15 | ms=-1 16 | -------------------------------------------------------------------------------- /mpv/scr/mpv-menu-plugin_v2.1_btime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/scr/mpv-menu-plugin_v2.1_btime.png -------------------------------------------------------------------------------- /mpv/scr/mpv-menu_jump_seek.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/scr/mpv-menu_jump_seek.png -------------------------------------------------------------------------------- /mpv/scr_mpv_avg-bitrate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/scr_mpv_avg-bitrate.jpg -------------------------------------------------------------------------------- /mpv/settings/scripts/avg-bitrate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* --- avg-bitrate.js mpv script --- */ 4 | /* v0.20 by butterw (2023/08/07), tested on Windows 5 | this version of avg-bitrate.js uses the new user-data feature (requires mpv v0.36). 6 | https://github.com/butterw/bShaders/blob/master/mpv/settings/scripts/avg-bitrate.js 7 | 8 | - avg-bitrate.js v0.11 might be a better starting point for writing custom osd scripts, and doesn't use user-data: 9 | https://github.com/butterw/bShaders/blob/e6827e3363310804d1a2ed03bd1cec5b7bb67aba/mpv/settings/scripts/avg-bitrate.js 10 | 11 | Calculates the average bitrate of the loaded audio-video file (in kilobits per second). 12 | The result is stored in the property user-data/avg-bitrate (ex: 1726 kb/s). 13 | 14 | To install, copy this script to the mpv subfolder: .\portable_config\scripts (assuming a Windows portable install). 15 | Check you have only one version of avg-bitrate in scripts to avoid confusion/conflicts. 16 | 17 | Basic use: 18 | display avg-bitrate on osd for 2 seconds when you press key a: 19 | input.conf: a no-osd show-text "${user-data/avg-bitrate}" 2000 20 | 21 | How to toggle a custom osd with a keybinding (the osd is permanently visible until disabled, it updates when a new file is loaded): 22 | mpv.conf or mpv cli: --osd-msg2="${filename}\n${file-size}\n${user-data/avg-bitrate}" 23 | input.conf: O no-osd cycle-values osd-level 2 1 24 | 25 | Audio/video file average bitrate calculation using filesize_Bytes/duration_s: 26 | avg-bitrate (in kilobits per second, kb/s) = 8/1000.0 * file-size_bytes / duration_s 27 | for local video/audio files seems to match `mediainfo > Overall bit rate`. 28 | Note that the file duration is not always exactly known, so this is an estimate. 29 | avg-bitrate returns an empty string in the following cases: 30 | ! images have duration: 0 31 | ! video streamed with yt-dlp have filesize: NaN 32 | use video-bitrate property instead. 33 | 34 | In some cases, the (keyframe based) `video-bitrate` property isn't very useful: 35 | - it is (undefined) at the start of the video and after seeks (calculation requires two keyframes). 36 | - it varies a lot on some medium/low bitrate video. 37 | 38 | */ 39 | 40 | var filesize_Bytes = 0.0; 41 | var duration_s = 0.0; 42 | var bitrate_kbps; 43 | 44 | // function is run every time a new file is loaded: 45 | mp.register_event("file-loaded", function() { 46 | filesize_Bytes = mp.get_property_number("file-size"); 47 | duration_s = mp.get_property_number("duration"); 48 | bitrate_kbps = ""; 49 | 50 | if ((duration_s>0) && !isNaN(filesize_Bytes)) { 51 | bitrate_kbps = Math.round(0.008*filesize_Bytes/duration_s); 52 | print(bitrate_kbps, "kb/s"); //[avg-bitrate] 1710 kb/s 53 | bitrate_kbps = bitrate_kbps +" kb/s"; 54 | } 55 | 56 | mp.set_property("user-data/avg-bitrate", bitrate_kbps); 57 | }); 58 | -------------------------------------------------------------------------------- /mpv/settings/scripts/btime.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/settings/scripts/btime.js -------------------------------------------------------------------------------- /mpv/settings/scripts/btime_osd-bar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/settings/scripts/btime_osd-bar.jpg -------------------------------------------------------------------------------- /mpv/settings/scripts/countdown.lua: -------------------------------------------------------------------------------- 1 | --[[ countdown.lua mpv script 2 | v0.12 by butterw (2023/08) 3 | 4 | Displays a COUNTDOWN in seconds for the final seconds of the video (or music file). 5 | This is done by setting osd-msg1. 6 | 7 | To load this script at startup: --script=path.to/countdown.lua 8 | 9 | --]] 10 | 11 | mp.observe_property("time-remaining", "number", function(name, value) 12 | 13 | local s = 30 -- set the max NUMBER OF SECONDS to countdown. 14 | 15 | if value ~=nil and value mpv --glsl-shaders=abba.glsl video.mp4 7 | displays in terminal, in red: 8 | [file] Cannot open file 'abba.glsl': No such file or directory 9 | Failed to open abba.glsl. 10 | 11 | --log-file=my.log 12 | [ 0.011][v][cplayer] Setting option 'glsl-shaders' = 'abba.glsl' (flags = 8) 13 | ... 14 | [ 0.074][e][file] Cannot open file 'abba.glsl': No such file or directory 15 | [ 0.075][e][stream] Failed to open abba.glsl. 16 | 17 | 18 | 19 | log-message (MPV_EVENT_LOG_MESSAGE) 20 | This contains, in addition to the default event fields, the following fields: 21 | prefix: The module prefix, identifies the sender of the message. This is what the terminal player puts in front of the message text when using the --v option, and is also what is used for --msg-level. 22 | level: The log level as string. See msg.log for possible log level names. Note that later versions of mpv might add new levels or remove (undocumented) existing ones. 23 | text: The log message. The text will end with a newline character. Sometimes it can contain multiple lines. 24 | Keep in mind that these messages are meant to be hints for humans. You should not parse them, and prefix/level/text of messages might change any time. 25 | 26 | ]]-- 27 | local ov = mp.create_osd_overlay("ass-events") 28 | 29 | mp.enable_messages('error') 30 | mp.register_event('log-message', function(log) 31 | message = "{\\c&H0000CC>&}[" .. log.prefix .. "] " .. log.text 32 | if log.prefix == "file" then 33 | ov.data = ov.data .. message 34 | ov:update() 35 | 36 | mp.add_timeout(4, function () 37 | local endln = ov.data:find('\n') + 1 38 | ov.data = ov.data:sub(endln) 39 | ov:update() 40 | end) 41 | end 42 | end) -------------------------------------------------------------------------------- /mpv/settings/scripts/menu_window_scale.lua: -------------------------------------------------------------------------------- 1 | local scales = {0.5, 0.75, 1, 1.25, 1.5, 2} -- choose menu values 2 | local keyword = 'window-scale' 3 | 4 | -- menu_window_scale.lua mpv script, 5 | -- by butterw (2024-01-18) 6 | -- 7 | -- Simple custom dynamic menu example using mpv-menu-plugin v2.1 with dyn_menu.lua, req mpv0.37 on windows. 8 | -- Adds a Scale menu populated with window-scale values (configured in scales variable), this script ensures the current value is checked. 9 | -- input.conf: _ ignore #menu: Scale #@window-scale 10 | -- Screenshot: https://github.com/butterw/bShaders/commit/2484df7cfcdedfa1be8d513ab603ed92e83d275f 11 | 12 | local utils = require('mp.utils') 13 | local function printd(pre, x) print(pre, utils.to_string(x)) end --printd("x:", x) 14 | 15 | -- initial menu setup 16 | local submenu={} 17 | for _, elt in ipairs(scales) do 18 | local pre = elt==1 and '=' or '' --adds '=' menu accelerator for the value 1.0 19 | submenu[#submenu + 1] = { 20 | title = pre..elt ..'x', 21 | cmd = string.format('set fullscreen no; set window-scale %s', elt), -- the command that will be applied. 22 | state = {} 23 | } 24 | end 25 | 26 | -- wait until the menu is ready, then get menu info for desired keywords 27 | mp.register_script_message('menu-ready', function() 28 | -- print('menu-ready'); 29 | mp.commandv('script-message-to', 'dyn_menu', 'get', keyword, mp.get_script_name()) 30 | end) 31 | 32 | -- if keyword is present (in input.conf), observe property window-scale 33 | mp.register_script_message('menu-get-reply', function(data) 34 | local reply = utils.parse_json(data) 35 | -- printd("reply:", reply) 36 | -- printd("error:", reply.error) 37 | if not reply.error and reply.keyword == keyword then mp.observe_property(keyword, 'native', window_scale_checklist_cb) end 38 | end) 39 | 40 | -- update checked state of submenu entries based on window-scale value 41 | function window_scale_checklist_cb(_, value) 42 | -- print(_, value) 43 | if value == nil then return end 44 | 45 | for i, elt in ipairs(scales) do 46 | local state = elt==value and {'checked'} or {} 47 | submenu[i].state = state 48 | end 49 | local item = {type='submenu'} 50 | item.submenu = submenu 51 | -- printd("item:", item) 52 | mp.commandv('script-message-to', 'dyn_menu', 'update', keyword, utils.format_json(item)) 53 | end 54 | -------------------------------------------------------------------------------- /mpv/settings/scripts/mpv-menu_dynamic_win10-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/settings/scripts/mpv-menu_dynamic_win10-dark.png -------------------------------------------------------------------------------- /mpv/settings/scripts/mpv-menu_win10-light-1440p-hidpi125_pause-indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/settings/scripts/mpv-menu_win10-light-1440p-hidpi125_pause-indicator.png -------------------------------------------------------------------------------- /mpv/settings/scripts/obs_countdown.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* --- obs_countdown.js mpv script --- */ 4 | /* v0.11 by butterw (2023/08) 5 | 6 | Displays a countdown in seconds for the final seconds of the video. 7 | This is done by writing to osd-msg1. 8 | 9 | to load this script at startup: --script=path.to/obs_countdown.js 10 | */ 11 | 12 | mp.observe_property("time-remaining", "number", function (name, value) { 13 | var s = 30; // sets the max number of seconds to countdown. 14 | if (value==undefined || value>s) { 15 | mp.command('no-osd set osd-msg1 ""'); 16 | return; 17 | } 18 | s = "-"+ Math.round(value) +"s"; 19 | mp.command("no-osd set osd-msg1 "+ s); //ex: -30s 20 | //if (mp.get_property("eof-reached")=="yes") mp.command('no-osd set osd-msg1 ""'); //clears the text after 0s. 21 | }); -------------------------------------------------------------------------------- /mpv/settings/scripts/restart-mpv.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | mp.add_key_binding("Shift+F5", "restart-mpv", restart_mpv); // input.conf: Shift+F5 script-binding restart-mpv 3 | //mp.register_script_message("restart-mpv", restart_mpv); // input.conf: Shift+F5 script-message restart-mpv 4 | 5 | /* --- restart-mpv.js (mpv script) --- */ 6 | /* v0.21 by butterw (2023/12). tested on Win10. 7 | v0.20 requires mpv v0.37-dev (v0.37.0-70-g562450f5) 8 | v0.11 by butterw (2023/12/06), tested on Win10 with mpv 0.36 and 0.37-dev. 9 | 10 | restarts mpv: keeps current shaders (and recompiles them if the source code was modified). 11 | 12 | With mpv v0.37-dev, restart-mpv can now be done directly without any script required: 13 | input.conf: F5 run mpv.com --glsl-shaders=${glsl-shaders} --start=${playback-time} --pause=${pause} "${path}"; 14 | 15 | */ 16 | 17 | function restart_mpv() { 18 | var s = "--glsl-shaders="+ mp.get_property("glsl-shaders"); 19 | print("restart mpv", s); 20 | mp.commandv("run", "mpv.com", mp.get_property("path"), s); 21 | mp.command("quit"); 22 | } 23 | -------------------------------------------------------------------------------- /mpv/settings/scripts/scr_mpv_show-shaders.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/settings/scripts/scr_mpv_show-shaders.jpg -------------------------------------------------------------------------------- /mpv/settings/scripts/seek-bar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/mpv/settings/scripts/seek-bar.jpg -------------------------------------------------------------------------------- /mpv/settings/scripts/store-shaders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // store/restore shaders script for mpv by butterw (v0.1) 4 | // put in .\portable_config\scripts mpv subfolder. 5 | // input.conf: F10 script-message store-shaders 6 | // https://mpv.io/manual/stable/#javascript 7 | 8 | var is_first_run = true 9 | var shaders = "" 10 | function store_shaders() { //store current shader config on first run, this config will be restored by subsequent calls 11 | if (is_first_run ) { 12 | // print("store-shaders", is_first_run) 13 | var s = mp.get_property("glsl-shaders") 14 | if (s) { shaders = s; is_first_run = false;} 15 | } else { mp.set_property("glsl-shaders", shaders.replace(/,/g, ";"));} //js global string replacement ! 16 | } 17 | mp.register_script_message("store-shaders", store_shaders); 18 | mp.add_key_binding("F10", "store-shaders", store_shaders); //hotkey will be overriden by input.conf if a binding for the same key is defined or pre-defined. 19 | store_shaders() //optional: auto-store initial shader config 20 | -------------------------------------------------------------------------------- /mpv/settings/scripts/switch-shader.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var shaders_status= [] 3 | var vf_status= [] 4 | 5 | // put in .\portable_config\scripts subfolder. 6 | // input.conf: CTRL+p script-message switch-shaders 7 | // input.conf: CTRL+l script-message switch-vf 8 | // modified from https://github.com/mpv-player/mpv/issues/8512 by butterw 9 | // - v0.1 added similar functionality for ffmpeg video filters (vf) 10 | // doc: https://mpv.io/manual/stable/#javascript 11 | 12 | 13 | mp.register_script_message("switch-shaders", function() { 14 | var shaders_str = mp.get_property("glsl-shaders"); 15 | if (!shaders_str.length && shaders_status.length) { //shaders-on: restore glsl-shaders (but only if empty!) 16 | shaders_status.forEach(function(shader) {mp.commandv("change-list", "glsl-shaders", "append", shader)}); 17 | mp.osd_message(mp.get_property("glsl-shaders"), 0.5) 18 | print("shaders-on:", shaders_status) 19 | shaders_status = [] 20 | } else { //shaders-off: store current glsl-shaders 21 | shaders_status = mp.get_property("glsl-shaders").split(',') 22 | mp.set_property("glsl-shaders", "") 23 | mp.osd_message("shaders-off", 0.5) 24 | print("shaders-off", shaders_status) 25 | } 26 | }); 27 | 28 | mp.register_script_message("switch-vf", function() { 29 | var vf_str = mp.get_property("vf"); 30 | if (!vf_str.length && vf_status.length) { //video filter-on: restore vf (but only if vf is empty!) 31 | vf_status.forEach(function(vfilter) {mp.commandv("change-list", "vf", "append", vfilter)}); 32 | print("vf-on:", vf_status) //mp.msg.info() 33 | vf_status = [] 34 | } else { //vfilter-off: store current vf 35 | vf_status = mp.get_property("vf").split(',') 36 | mp.set_property("vf", "") 37 | mp.osd_message("vf-off", 0.5) 38 | print("vf-off", vf_status) 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /mpv/vibrance_next.hk: -------------------------------------------------------------------------------- 1 | //!PARAM vibr 2 | //!DESC Saturates/deSaturates 3 | //!TYPE float 4 | //!MINIMUM -1 5 | 0.35 6 | 7 | //!HOOK MAIN 8 | //!BIND HOOKED 9 | //!DESC vibrance_n(vibr) 10 | 11 | /* --- vibrance_next (mpv glsl.hook, req. vo_gpu-next) --- */ 12 | /* v1.35 (2023-07) released by butterw under GPLv3 13 | (1 texture, 9 arithmetic). 14 | 15 | Smart saturation/desaturation. Protects skin tones from excessive adjustments. 16 | 17 | - Vibrance parameter, [-1, 1.0], 0: no effect 18 | >> Positive: saturates low-saturation pixels first, ex: 0.35 19 | negative: reduces saturation of high-saturation pixels first, ex: -0.15 20 | 21 | Simplified version of SweetFx.Vibrance. 22 | Calculates a saturation measure, then applies saturation based on it. 23 | Affects color only, no effect on grays. 24 | */ 25 | 26 | #define CoefLuma vec4(0.2126, 0.7152, 0.0722, 0) //sRGB, HDTV 27 | 28 | vec4 hook() { 29 | vec4 c0 = HOOKED_texOff(0); 30 | float colorSat = max(max(c0.r, c0.g), c0.b) -min(min(c0.r, c0.g), c0.b); // >=0, 5 arithmetic 31 | 32 | c0.rgb = mix(vec3(dot(c0, CoefLuma)), c0.rgb, 1+vibr -colorSat*abs(vibr)); 33 | return c0; 34 | } 35 | -------------------------------------------------------------------------------- /test_LimitedRange/Avidemux/Settings/Custom/Readme.md: -------------------------------------------------------------------------------- 1 | This folder contains Avidemux TinyPy plugin scripts. 2 | 3 | They can be installed to menu > Custom (copy to settings/custom) or menu > Auto. 4 | 5 | They can also be run with the (File > Project > Run Script) command. 6 | 7 | -------------------------------------------------------------------------------- /test_LimitedRange/Avidemux/Settings/Custom/_ix.py: -------------------------------------------------------------------------------- 1 | # Configurable seek (Backward) 2 | # requires Avidemux>=v2.7.7 3 | # this script can be installed to GUI menu (copy to settings/custom) 4 | # https://github.com/butterw/bShaders/blob/master/test_LimitedRange 5 | 6 | seek_s=120 7 | ## 3) keyframe-seek, using a approximate time (seek_s) in seconds 8 | 9 | header_str = "seek_backward" ##v0.1 10 | adm=Avidemux(); ed=Editor(); gui=Gui() 11 | sec = 1000*1000 12 | 13 | nSegm = ed.nbSegments() 14 | if not nSegm: 15 | gui.displayError(header_str, "No video loaded !") 16 | return 17 | 18 | c = ed.getCurrentPts() 19 | adm.setCurrentPts(c -seek_s*sec) 20 | 21 | ## 2) keyframe-seek based on fixed number of keyframes (k) 22 | # works fine, but keyframe duration can vary a lot (from 1 frame to 10s typ and up to 20s) 23 | # k=-10; adm.seekKeyFrame(k) 24 | 25 | ## 1) time based seek (seek_s) in seconds 26 | # seek_s=60 27 | # c = ed.getCurrentPts() 28 | # adm.setCurrentPts(c + seek_s*sec) 29 | 30 | ## 0) seek based on fixed time (pts) 31 | # ! if the pts time value doesn't exactly match a frame, it will seek to the previous keyframe 32 | # pts=30*sec; adm.setCurrentPts(pts) 33 | 34 | #Seek to first frame: adm.setCurrentPts(0) 35 | -------------------------------------------------------------------------------- /test_LimitedRange/Avidemux/Settings/Custom/_ixxx.py: -------------------------------------------------------------------------------- 1 | # Configurable seek (Forward) 2 | # requires Avidemux>=v2.7.7 3 | # install this script to the Custom menu (copy to settings/custom) 4 | # https://github.com/butterw/bShaders/blob/master/test_LimitedRange 5 | #_ixxx.py v0.13 6 | 7 | seek_s=120 8 | ## 3) keyframe-seek of about (seek_s) in seconds 9 | 10 | adm=Avidemux(); ed=Editor() 11 | sec = 1000*1000 12 | 13 | if not ed.nbSegments(): return 14 | c = ed.getCurrentPts() 15 | adm.setCurrentPts(c +seek_s*sec) 16 | if c<20*sec: adm.seekKeyFrame(1) 17 | -------------------------------------------------------------------------------- /test_LimitedRange/Avidemux/Settings/Custom/adm-vThumb_UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_LimitedRange/Avidemux/Settings/Custom/adm-vThumb_UI.png -------------------------------------------------------------------------------- /test_LimitedRange/Avidemux/Settings/Custom/bSegments.py: -------------------------------------------------------------------------------- 1 | # List Segments (ref video file, duration, start time) and jump to the selected Segment. 2 | # Segments are created by edit or append operations. Displays segments >1 and up to MaxSegments. 3 | # requires Avidemux>=v2.7.7 4 | # this script can be installed to menu > custom (copy to settings/custom) 5 | # https://github.com/butterw/bShaders/blob/master/test_LimitedRange 6 | # bSegments.py v0.12 7 | 8 | header_str = "Segments" 9 | MaxSegments = 10 #the max number of segments to display 10 | adm=Avidemux(); ed=Editor(); gui=Gui() 11 | sec = 1000*1000 12 | 13 | try: splitext("test.abc") 14 | except: 15 | gui.displayError(header_str, "Avidemux2.7.7 or later required !") 16 | return 17 | nSegm = ed.nbSegments() 18 | if nSegm<2: print("Requires at least 2 Segments !"); return -1 #segments check! 19 | N = min(nSegm, MaxSegments) 20 | 21 | 22 | def str3f(x): 23 | # returns str(x rounded to 3 decimals) 24 | # str3f(16/9): "1.778" 25 | out_str = str(int(x)) 26 | if x==int(x): return out_str # ex:30 27 | x=abs(x) 28 | x=round((x-int(x))*1000) 29 | if x<10: pad = "00" 30 | elif x<100: pad = "0" 31 | else: pad = "" 32 | return out_str + "." + pad + str(x) 33 | 34 | def strPts(pts, fmt=""): 35 | # "00:02:31.865" or "Pts 00:02:31.865" 36 | # fmt=0 "t: 151.865000" 37 | t = pts*1/sec 38 | if fmt==0: return "t: " + str(t) 39 | th = int(t/3600) 40 | tm = int((t-th)/60) 41 | ts = t-th*3600-tm*60 42 | ts_str = str3f(ts) 43 | if th<10: th_str = "0" + str(th) 44 | else: th_str = str(th) 45 | if tm<10: tm_str = "0" + str(tm) 46 | else: tm_str = str(tm) 47 | if ts<10: ts_str = "0" + ts_str 48 | return fmt + th_str +":"+ tm_str +":"+ ts_str 49 | 50 | def toMinutesSeconds(pts, sep="m"): 51 | # result is rounded, ex: "2min43" or "2m43" 52 | sec = 1000*1000 53 | seconds = pts*1/sec 54 | minutes = int(seconds*1/60) 55 | seconds = round(seconds -minutes*60) 56 | str0=""; if seconds<10: str0="0" 57 | return str(minutes) +sep+ str0+str(seconds) 58 | 59 | nVid = ed.nbVideos() 60 | cPts = ed.getCurrentPts() 61 | segments_pts = [] #segments start pts table 62 | refVideos = [] 63 | lines = [] 64 | endI = 0 #endI: current segment end 65 | cIdx = -1 #cIdx: the current segmentIdx 66 | for idx in range(N): 67 | endP = endI #prev segment end 68 | dI = ed.getDurationForSegment(idx) 69 | refI = ed.getRefIdxForSegment(idx) 70 | endI+= dI 71 | if cIdx is -1 and cPts0 and ed.getTimeOffsetForSegment(idx)==0: 73 | kPts = ed.getNextKFramePts(endP-1) 74 | else: kPts=endP 75 | segments_pts.append(kPts) 76 | refVideos.append(refI) 77 | line = "["+str(idx) 78 | if nVid>1: line+= ":v"+str(refI) 79 | line+= "] "+ strPts(kPts) +" ("+ toMinutesSeconds(dI) +")" 80 | lines.append(line) 81 | 82 | ## Display 83 | title_str = header_str +": "+str(nSegm) 84 | if nVid>1: title_str+= "/v"+ str(nVid) 85 | dlgWizard = DialogFactory(title_str) 86 | label_str = "["+ str(cIdx) +"] "+ strPts(cPts) 87 | mnu = DFMenu(label_str) # "_" is discarded in the label !!! 88 | for item in lines: mnu.addItem(item) 89 | display_idx = min(cIdx+1, nSegm-1) 90 | mnu.index = min(display_idx, N-1) 91 | dlgWizard.addControl(mnu) 92 | res = dlgWizard.show() 93 | 94 | if res==1: adm.setCurrentPts(segments_pts[mnu.index]) 95 | -------------------------------------------------------------------------------- /test_LimitedRange/Avidemux/Settings/Custom/black_A-B.py: -------------------------------------------------------------------------------- 1 | # adds filter (black) based on marker A and B positions. 2 | 3 | adm=Avidemux(); ed=Editor(); gui=Gui() 4 | if not ed.nbSegments(): 5 | gui.displayError("black_A[B", "No video loaded !") 6 | return 7 | adm.addVideoFilter("black", "startBlack="+str(adm.markerA/1000), "endBlack="+str(adm.markerB/1000)) 8 | -------------------------------------------------------------------------------- /test_LimitedRange/Avidemux/Settings/Custom/saveFull.py: -------------------------------------------------------------------------------- 1 | # Save the full video not just the selection without resetting markers 2 | # also displays some extra info in the title of the save dialog (ex: 1min20 2/1 0a) 3 | # duration in minutes+seconds, if more than one: nbSegments / nbVideos, the number of audio tracks 4 | # this script can be installed to settings/custom GUI menu 5 | # https://github.com/butterw/bShaders/blob/master/test_LimitedRange 6 | 7 | header_str = "saveFull" ##v0.2 8 | adm=Avidemux(); ed=Editor(); gui=Gui() 9 | 10 | def fileWriteSelect(title="Please Select output file", ext=None): 11 | # by default uses the GUI output extension in the WriteSelect Dialog 12 | #ex: fileWriteSelect(); fileWriteSelect("Title"); fileWriteSelect(ext="mp4"); fileWriteSelect("Title", "mp4") 13 | if ext is None: ext=adm.getOutputExtension() 14 | return gui.fileWriteSelectEx(title, ext) #Req Avidemux>=2.7.7 15 | 16 | def toMinutesSeconds(pts): 17 | # ex result: "2min43" 18 | sec = 1000*1000 19 | seconds = pts*1/sec 20 | minutes = int(seconds*1/60) 21 | seconds = round(seconds - minutes*60) 22 | str0=""; if seconds<10: str0="0" 23 | return str(minutes) +"min" +str0+str(seconds) 24 | 25 | nSegm = ed.nbSegments() 26 | if not nSegm: 27 | gui.displayError(header_str, "No video loaded !") 28 | return 29 | 30 | nAudio = adm.audioTracksCount() 31 | audio_str="" 32 | if nAudio==0 or nAudio>1: 33 | audio_str= " " + str(nAudio) +"a" 34 | end = ed.getVideoDuration() 35 | title = toMinutesSeconds(end) + " " 36 | segm_str = str(nSegm) +"/"+ str(ed.nbVideos()) 37 | if segm_str != "1/1": title+= segm_str 38 | title+= audio_str 39 | title+= ": Select file to save(Full)" 40 | 41 | fpath = fileWriteSelect(title) 42 | if fpath is None: gui.displayError(header_str, "No Output file selected !"); return 43 | # Full Save without losing Markers: 44 | A = adm.markerA 45 | B = adm.markerB 46 | adm.markerA = 0 47 | adm.markerB = end 48 | adm.save(fpath) 49 | adm.markerA = A 50 | adm.markerB = B 51 | -------------------------------------------------------------------------------- /test_LimitedRange/ColorBarsHD_720p.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_LimitedRange/ColorBarsHD_720p.mp4 -------------------------------------------------------------------------------- /test_LimitedRange/ColorBarsHD_full_avs720p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_LimitedRange/ColorBarsHD_full_avs720p.jpg -------------------------------------------------------------------------------- /test_LimitedRange/Readme.md: -------------------------------------------------------------------------------- 1 | ## Limited Range Tests 2 | 3 | - bHighL.hlsl: out of range Luma highlighting pixel shader 4 | - ffm4b.bat: ffmpeg lossless commands (Windows bat file), incl. changing video bitstream range tag 5 | - convert a test image to video with correct colors with ffmpeg 6 | 7 | Avisynth scripts: 8 | * gen_ColorBarsHD.avs 9 | * LumaHistogram.avs (dynamic display of a video file luma histogram) 10 | * Luma_stats.avs: generates a .csv of per frame Luma statistics of a video file (Y: min, 0.4%Low, med, mean, 0.4%High, max, mean_diff with previous frame) 11 | * generate ColorBarsHD test pattern with Avisynth+ 12 | 13 | #### ColorBarsHD: 14 | The difference between an expanded and a non expanded limited range is most visible on White. 15 | * avs_rec709_720p-full.png: 16 | ![](https://github.com/butterw/bShaders/blob/master/test_LimitedRange/avs_rec709_720p-full.png?raw=true) 17 | * avs_pc.709_720p-001.png: 18 | ![](https://github.com/butterw/bShaders/blob/master/test_LimitedRange/avs_pc.709_720p-001.png?raw=true) 19 | 20 | The output can be encoded to x264 .mp4 with ffmpeg: 21 | ``` 22 | ffmpeg -i gen_ColorBarsHD.avs -an -t 60 -c:v libx264 -pix_fmt yuv420p -tune stillimage -preset veryslow -crf 12 ColorBarsHD.mp4 23 | ``` 24 | 25 | #### Convert a color card image to video with correct colors, ex: to test response of video player shaders or lut: 26 | ![](https://github.com/butterw/bShaders/blob/master/test_LimitedRange/graycard9_0-32-64-96-128-159-191-223-255.bmp?raw=true) 27 | ``` 28 | ffmpeg -loop 1 -framerate 1 -i graycard9_0-32-64-96-128-159-191-223-255.bmp -c:v libx264 -t 15 -r 30 -pix_fmt yuv420p -tune stillimage graycard9_1392x336p30-15s_0-32-64-96-128-159-191-223-255.mp4 29 | ``` 30 | - Crop the input image to get mod-4 or better resolution. Save as lossless format. 31 | - Generate mp4 output video compressed with x264, the specified framerate is 30fps and the duration is 15s. 32 | - You can check colors on screen using freeware color picker software (ex: Just Color Picker on Windows). When displayed in video player, color error will be at most a single RGB8 level. 33 | -------------------------------------------------------------------------------- /test_LimitedRange/avs_pc.709_720p-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_LimitedRange/avs_pc.709_720p-001.png -------------------------------------------------------------------------------- /test_LimitedRange/avs_rec709_720p-full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_LimitedRange/avs_rec709_720p-full.png -------------------------------------------------------------------------------- /test_LimitedRange/bHighL.hlsl: -------------------------------------------------------------------------------- 1 | #define Red float4(1, 0, 0, 0) 2 | #define Yellow float4(1, 1, 0, 0) 3 | #define Green float4(0, 1, 0, 0) 4 | #define Blue float4(0, 0, 1, 0) 5 | 6 | /*--- User Configuration ---*/ 7 | #define HighColor Yellow //Red 8 | #define LowColor Green 9 | 10 | #define HighLimit 235/255. 11 | #define LowLimit 14/255. 12 | 13 | 14 | /*--- bHighL.hlsl by butterw v0.1 15 | Highlights pixels outside of defined Luma Range (in solid colors) 16 | Limited Range Luma: 16-235 (vs Full Range Luma: 0-255) 17 | 18 | 19 | (1 texture, 5 arithmetic) 20 | */ 21 | #define CoefLuma float4(0.212656, 0.715158, 0.072186, 0) // BT.709 & sRBG luma coef (HDTV, SDR Monitors) 22 | sampler s0: register(s0); 23 | 24 | float4 main(float2 tex: TEXCOORD0): COLOR { 25 | float4 c0 = tex2D(s0, tex); 26 | float4 luma = dot(c0, CoefLuma); 27 | 28 | return (luma>HighLimit) ? HighColor: 29 | (lumaProject Script... or add to Custom menu) 5 | # 6 | # Insert a video file into your file before the current position 7 | # If you have edited your file, save it and reload it before proceeding ! 8 | # for no re-encoding mode: 9 | # - Insertion point must be on a Keyframe ! 10 | # - encoding parameters must match ! 11 | 12 | adm=Avidemux(); ed=Editor(); gui=Gui() 13 | sec = 1000*1000 #timestamps and duration are reported in us. to convert to seconds *1/sec. 14 | 15 | nSegm = ed.nbSegments() 16 | if nSegm!=1: 17 | if not nSegm: msg_str="No video loaded !" 18 | else: 19 | msg_str ="Multiple Segments detected !\n" 20 | msg_str+="Please Save and Reload Your File" 21 | gui.displayError("bInsert", msg_str) 22 | return 23 | 24 | ## Insert at current position I 25 | I = ed.getCurrentPts() 26 | if I<0.3*sec: gui.displayError("bInsert", "Set Insertion Point I >0.3s"); return 27 | end0 = ed.getVideoDuration() 28 | try: 29 | title_str = "bInsert (I="+ str(round(I*1/sec)) +"s): Select File to Insert" 30 | fname_ins = gui.fileReadSelect(title_str) #None if Cancel 31 | if fname_ins is None: gui.displayError("bInsert", "No input file selected"); return 32 | except: 33 | gui.displayError("bInsert", "No input file selected"); return 34 | # fname_ins = "B:/Videos/ins.mp4" 35 | adm.seekKeyFrame(99999) 36 | adm.markerA=0; adm.markerB=end0 #reset Markers 37 | if not adm.appendVideo(fname_ins): raise("Cannot append " +str(fname_ins)) 38 | ff01 = ed.getNextKFramePts(-1) 39 | end = ed.getVideoDuration() 40 | adm.clearSegments() 41 | adm.addSegment(0, 0, I) 42 | adm.addSegment(1, ff01-end0, end-end0) 43 | adm.addSegment(0, I, end0-I) 44 | adm.seekKeyFrame(-1) #getting some crashes trying to preview without this ? 45 | adm.markerA=0; adm.markerB=end #reset Markers 46 | print("bInsert done:", I, ed.getCurrentPts(), end) 47 | -------------------------------------------------------------------------------- /test_LimitedRange/bSplit.py: -------------------------------------------------------------------------------- 1 | ## bSplit.py Lossless Video Split for Avidemux GUI 2 | # https://github.com/butterw/bShaders/tree/master/test_LimitedRange 3 | # 4 | # tested in Avidemux 2.7.7dev (run with File>Project Script or add to Custom menu by copying to ./settings/custom) 5 | # 6 | # Split points are on manually selected with current position, 7 | # and with A,B markers if they are set (to unset them use Edit > Reset Markers). Meaning you can split the loaded video in 2 to 4 parts. 8 | # Output files will be named p1,2,3,4_filename based on the filename you provide. Any file with the same name will be overwriten. 9 | # To avoid overlap between sections, split point should be on keyframes and B_is_not_included_save_mode should be set to 1 10 | # By default, Avidemux saves the frame corresponding to marker B. This is necessary for open-gop videos, but will cause 1 duplicate frame if the split sections are recombined. 11 | B_is_not_included_save_mode = 1 # [0 or 1] 12 | header_str = "bSplit" 13 | adm=Avidemux(); ed=Editor(); gui=Gui() 14 | sec = 1000*1000 #timestamps and duration are reported in us. to convert to seconds *1/sec. 15 | 16 | if not ed.nbSegments(): gui.displayError(header_str, "No video loaded !"); return 17 | 18 | I = ed.getCurrentPts() 19 | A = adm.markerA 20 | B = adm.markerB 21 | end = ed.getVideoDuration() 22 | 23 | splits = [I, A, B]; splits.sort() 24 | valid_splits=[] 25 | for elt in splits: 26 | if elt>0.3*sec and elt0.3s !"); return 29 | 30 | title_str = header_str + "(I, A, B): " 31 | title_str+= str(n) + " output files will be named pX-filename" 32 | try: 33 | fname = gui.fileWriteSelect(title_str) 34 | if fname is None: gui.displayError(header_str, "No Output file selected !"); return 35 | except: 36 | gui.displayError(header_str, "No Output file selected"); return 37 | print(header_str, fname) 38 | 39 | valid_splits=[0]+valid_splits+[end] 40 | for i in range(n): 41 | i+=1 42 | adm.markerA = valid_splits[i-1] 43 | if iProject Script or add to Custom menu) 5 | 6 | ext="mp4" 7 | 8 | adm=Avidemux(); ed=Editor(); gui=Gui() 9 | header_str = "dirLoad" 10 | nSegm = ed.nbSegments() 11 | if nSegm>0: gui.displayError(header_str, "Please Close Open File!"); return 12 | 13 | inputFolder = gui.dirSelect(header_str + "(" +ext+ "): Select folder") 14 | flist = get_folder_content(inputFolder, ext) 15 | if len(flist): 16 | print(header_str, len(flist), ext) 17 | if not adm.loadVideo(flist[0]): raise("Cannot load " + str(flist[0])) 18 | for fname in flist[1:]: 19 | if not adm.appendVideo(fname): raise("! Cannot append " +str(fname)) 20 | print(header_str + " done, Segments:", ed.nbSegments(), ed.getVideoDuration()) 21 | 22 | -------------------------------------------------------------------------------- /test_LimitedRange/ffm4b.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM https://forum.videohelp.com/threads/398507-Top10-Commands-for-Lossless-Video-manipulation-using-ffmpeg-(Guide) by butterw 4 | REM FFmpeg.exe must be available on the path ! 5 | echo FFmpeg Lossless Commands (ffm4b.bat) 6 | echo. 7 | 8 | 9 | REM percent sign must be doubled in .bat file (vs cmd command-line ) 10 | REM if you double-click the .bat, output dir will be the script dir 11 | REM # Prompt for fname, can contain spaces 12 | set /p fname="Please Paste/Enter full path filename: " 13 | 14 | 15 | for %%f in ("%fname%") do ( 16 | REM %%f full path filename, "%%~nf" filename only, "%%~xf" .extension only, "%%~dpnf" path + filename only 17 | echo REM Uncomment the command line you want to run ! 18 | echo fname: %%f 19 | echo. 20 | 21 | REM # Demux Audio as .m4a (input must have aac Audio for this operation to be lossless!) 22 | REM ffmpeg -hide_banner -i %%f -vn -c:a copy "%%~nf.m4a" 23 | 24 | REM # Convert fake stereo to mono (FR, Front Right channel to f_mono.m4a) 25 | REM # ffmpeg -hide_banner -i %%f -vn -af "pan=mono|FC=FR" "%%~nf_mono.m4a" 26 | 27 | REM # Output Video with muted Audio: filename_muted.ext 28 | REM ffmpeg -hide_banner -an -i %%f -c copy "%%~nf_muted%%~xf" 29 | 30 | REM # Convert/Remux to .mp4 31 | REM ffmpeg -hide_banner -i %%f -c copy "%%~nf.mp4" 32 | 33 | REM # Mux Video (f.mp4) and Audio (f.m4a) to f_mux.mp4 34 | REM ffmpeg -hide_banner -i %%f -i "%%~dpnf.m4a" -c copy -map 0:v -map 1:a "%%~nf_mux.mp4" 35 | 36 | REM Split a video into multiple parts based on duration (ex: 10min segments: f-000.mp4 f-001.mp4 f-002.mp4, cut on keyframes) 37 | REM ffmpeg -hide_banner -i %%f -c copy -segment_time 00:10:00 -f segment "%%~nf-%03d.mp4" 38 | 39 | REM # Optimize mp4 for the web, moves the moov atom to the start of the file 40 | REM ffmpeg -hide_banner -i %%f -c copy -movflags faststart "%%~nf_web.mp4" 41 | 42 | REM # Clockwise 90° Rotate (Flip) a mp4 video (.mp4 metadata)[/B] 43 | REM # Flip Right: 44 | REM ffmpeg -hide_banner -i %%f -c copy -metadata:s:v:0 rotate=90 "%%~nf_r90.mp4" 45 | 46 | REM # Flip Left: 47 | REM ffmpeg -hide_banner -i %%f -c copy -metadata:s:v:0 rotate=270 "%%~nf_r270.mp4" 48 | 49 | REM # Set the Display Aspect Ratio to the specified value (container DAR supported in .mp4, .mkv, ...) 50 | REM ffmpeg -hide_banner -i %%f -aspect 4:3 -c copy "%%~nf_DAR.mp4" 51 | 52 | REM # Cropping without Re-encoding (in video bitstream: h264, hevc, ...) 53 | REM ffmpeg -hide_banner -i %%f -c copy -bsf:v h264_metadata=crop_bottom=128:crop_top=0:crop_left=0:crop_right=0 "%%~nf_crop.mp4" 54 | REM ffmpeg -hide_banner -i %%f -c copy -bsf:v hevc_metadata=crop_bottom=128:crop_top=0:crop_left=0:crop_right=0 "%%~nf_crop.mp4" 55 | 56 | REM # Change color range to Full (in video bitstream: h264, hevc, ...) 57 | REM ffmpeg -hide_banner -i %%f -c copy -bsf:v h264_metadata=video_full_range_flag=1 "%%~nf_fullrange%%~xf" 58 | 59 | 60 | REM # Trim based on Duration -t OR Stop -to 61 | REM # if required you can specify a Start time -ss from the start OR from the end -sseof with negative time value 62 | REM # seconds format: 20 or 00:00:20.000 63 | REM # .m4a audio output example: 64 | REM ffmpeg -hide_banner -i %%f -t 45 -vn -c:a copy "%%~nf_cut.m4a" 65 | REM ffmpeg -hide_banner -i %%f -ss 15 -t 30 -vn -c:a copy "%%~nf_cut.m4a" 66 | REM ffmpeg -hide_banner -i %%f -ss 00:03:43 -vn -c:a copy "%%~nf_cut.m4a" 67 | REM ffmpeg -hide_banner -i %%f -to 00:03:00 -vn -c:a copy "%%~nf_cut.m4a" 68 | ) 69 | 70 | REM # Press any key to continue . . . 71 | pause 72 | -------------------------------------------------------------------------------- /test_LimitedRange/gen_ColorBarsHD.avs: -------------------------------------------------------------------------------- 1 | H=720 2 | W=1280 3 | colormatrix = "rec709"# #default: "rec709" Limited range vs Full: "pc.709" 4 | 5 | /* gen_ColorBarsHD.avs 6 | by butterw, v0.1 Avisynth script 7 | 8 | Generates ColorBarsHD video of the desired resolution with Full "pc.709" or Limited "rec709" Range 9 | - Full Range pc.709 keeps the range unchanged 10 | - rec709 expands 16-235 YUV to 0-255 RGB 11 | - set W x H resolution 12 | - you can offset YUV values with ColorYUV() 13 | - RGB32 or YV12 output, .avs can be opened by mpc-hc/be 14 | - Rgb32 output allows you to bypass default yuv-to-rgb conversion performed at the input of the video player (with range expansion in mpc-hc/be for a video stream not tagged as full range). 15 | 16 | Typical PC Display Pipeline: 17 | Compressed video file (yuv420p8, Limited Range, untagged) >>mpc-hc Video player (rgb32, range expanded to Full Range) >> graphics driver (rbg32 Output, Full Range) >> Hdmi >> Monitor (Full Range) 18 | - Historically TV/HDTV have used limited range input and PC monitor full RGB range. 19 | - Most current displays should allow you to set the desired input range (if you change this value, you probably also need to adjust brightness, contrast, gamma for good results). 20 | For accurate representation of grey levels and colors your monitor/HDTV and graphics settings should match: Full-PC or Limited-Low. 21 | 22 | Script was used to generate and save (rename was required !): 23 | - avs_pc.709_720p-001.png 24 | - avs_rec709_720p-002.png 25 | 26 | The ColorBarsHD test pattern contains colors in the YUV(Y'CbCr) format used by typical media files (ex: mp4\x264, x265): 27 | - Black: 16, 128, 128 28 | - White: 235, 128, 128 29 | 30 | Corresponding RGB values: 31 | - Black, Limited Range: 16, 16, 16 vs Full Range: 0, 0, 0 32 | - White, Limited Range: 235, 235, 235 vs Full Range: 255, 255, 255 33 | 34 | You can check these values using the YUV pixel picker tool of the AvsPmod editor output display or with any on-screen RGB pixel picker. 35 | Checking the colors as displayed by the monitor is more difficult (Calibration probe req. ?), but at minimum you must be able to control the input, which these test patterns allow you to do. 36 | */ 37 | ColorBarsHD(width=W, height=H) 38 | ConvertToYV12(matrix=colormatrix) 39 | ## ColorYUV(off_y=-16) 40 | #~ ConvertToRGB(matrix=colormatrix) 41 | Subtitle(String(PixelType) +" "+ colormatrix +" "+ string(Width) +"x"+ string(Height)) 42 | #~ fmt_str = "avs" + String(Height) + "p-" 43 | #~ ImageWriter(fmt_str, 1, 1, type = "png", info = true) ##Save a png image in the script directory 44 | -------------------------------------------------------------------------------- /test_LimitedRange/graycard9_0-32-64-96-128-159-191-223-255.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_LimitedRange/graycard9_0-32-64-96-128-159-191-223-255.bmp -------------------------------------------------------------------------------- /test_LimitedRange/graycard9_1392x336p30-15s_0-32-64-96-128-159-191-223-255.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_LimitedRange/graycard9_1392x336p30-15s_0-32-64-96-128-159-191-223-255.mp4 -------------------------------------------------------------------------------- /test_LimitedRange/luma_stats.avs: -------------------------------------------------------------------------------- 1 | /* luma_stats.avs 2 | analyse mp4 video file: for each frame calculate Luma stats (similar to ColorYUV(analyze=true)) 3 | output: luma.csv 4 | 5 | by butterw, tested on Avisynth+ v3.6.1 x64 6 | Run with: path_to\AVSMeter64.exe luma_stats.avs 7 | 8 | perf: 107fps on 1080p video 9 | */ 10 | fname_video = "b:\Videos\monster-1_ed.mp4" 11 | LSmashVideoSource(fname_video, prefer_hw=2) 12 | fname_stats = "luma.csv" 13 | sep = "; " 14 | header = "frame" +sep+ "Ymin" +sep+ "Ymin(0.4)" +sep+ "Ymed" +sep+ "Yavg" +sep+ "Ymax(0.4)" +sep+ "Ymax" 15 | WriteFileStart(fname_stats, "header", append=false) 16 | WriteFile(fname_stats, "current_frame", "sep", "YPlaneMin", "sep", "YPlaneMin(0.4)", "sep", "YPlaneMedian", "sep", "AverageLuma", "sep", "YPlaneMax(0.4)", "sep", "YPlaneMax", flush=false, append=true) 17 | -------------------------------------------------------------------------------- /test_LimitedRange/test_version.avs: -------------------------------------------------------------------------------- 1 | /* Basic avisynth test 2 | 3 | Displays the avisynth version on screen 4 | */ 5 | 6 | 7 | Version() -------------------------------------------------------------------------------- /test_linearSampling/Offset 0.5 Sampling artefact_zoomed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_linearSampling/Offset 0.5 Sampling artefact_zoomed.png -------------------------------------------------------------------------------- /test_linearSampling/Test_HW_Linear_Sampling.hook: -------------------------------------------------------------------------------- 1 | //!HOOK MAIN 2 | //!BIND HOOKED 3 | //!DESC Test_HW_Linear_Sampling 4 | 5 | /* mpv shader by butterw 6 | MAIN: rgba pre-resize */ 7 | 8 | #define Red vec4(1, 0, 0, 1) 9 | vec4 hook(){ 10 | vec4 color = HOOKED_texOff(0.5); 11 | if (abs(color.r-0.5)<0.01) return Red; 12 | return color; 13 | } -------------------------------------------------------------------------------- /test_linearSampling/bSmooth_test.hlsl: -------------------------------------------------------------------------------- 1 | #define Mode 10 2 | /* Mode [0, 1, 10] default:0 full (9 texture, 15 arithmetic), 3 | // 1: hw, uses hw linear sampling (4 texture, 7 arithmetic) faster but may not be supported 4 | //10: tests whether hw linear sampling is supported. Orange screen: not supported. 5 | 6 | Gaussian Smoothing Filter 7 | bSmooth_test.hlsl v0.1 8 | by butterw, License: GPL v3 9 | for maximum effect use pre-upscaling. 10 | 11 | // Gaussian filter 3x3, sigma=0.85, in multi-pass sigma=sigma*sqrt(2) 12 | // [ 1, 2, 1 ] 13 | // [ 2, 4, 2 ] 14 | // [ 1, 2, 1 ] 15 | */ 16 | 17 | sampler s0: register(s0); 18 | float2 p1: register(c1); 19 | #define px p1.x // pixel width 20 | #define py p1.y 21 | 22 | float4 main(float2 tex: TEXCOORD0): COLOR { 23 | float4 orig = tex2D(s0, tex); // get original pixel 24 | float4 blur; 25 | 26 | #if Mode==0 27 | //Gaussian filter 3x3 gSmooth3(9 texture, 15 arithmetic) 28 | blur = tex2D(s0, tex - p1); 29 | blur+= tex2D(s0, tex + float2( px, -py)); 30 | blur+= 2*tex2D(s0, tex + float2( 0, -py)); 31 | blur+= 2*tex2D(s0, tex + float2(-px, 0)); 32 | blur+= 4*orig; 33 | blur+= 2*tex2D(s0, tex + float2( px, 0)); 34 | blur+= 2*tex2D(s0, tex + float2( 0, py)); 35 | blur+= tex2D(s0, tex + float2(-px, py)); 36 | blur+= tex2D(s0, tex + p1); 37 | blur*= 0.0625; //div by 16 38 | 39 | #elif Mode==1 //hw.gSmooth3(4 texture, 7 arithmetic) 40 | #define po 0.5 //default: 0.5, 0.499: doesn't blur if hw linear sampling isn't supported. 41 | blur = tex2D(s0, tex + p1*float2(-po, -po)); 42 | blur+= tex2D(s0, tex + p1*float2( po, -po)); 43 | blur+= tex2D(s0, tex + p1*float2(-po, po)); 44 | blur+= tex2D(s0, tex + p1*float2( po, po)); 45 | blur*= 0.25; 46 | 47 | #elif Mode==10 //hw linear sampling test: Orange screen means not supported 48 | #define po 0.499 49 | #define Orange float4(1, 0.5, 0, 1) 50 | blur = tex2D(s0, tex + p1*float2(-po, -po)); 51 | blur+= tex2D(s0, tex + p1*float2( po, -po)); 52 | blur+= tex2D(s0, tex + p1*float2(-po, po)); 53 | blur+= tex2D(s0, tex + p1*float2( po, po)); 54 | blur*= 0.25; 55 | if (all(abs(orig-blur)<0.001)) return Orange; 56 | 57 | #elif Mode==2 // smooth(3+ [1 4 1]) kernel (5texture, 8 arithmetic) 58 | blur = tex2D(s0, tex + float2( 0, -py)); 59 | blur+= tex2D(s0, tex + float2(-px, 0)); 60 | blur+= 4*orig; 61 | blur+= tex2D(s0, tex + float2( px, 0)); 62 | blur+= tex2D(s0, tex + float2( 0, py)); 63 | blur*= 0.125; 64 | #endif 65 | // return 5*abs(orig-blur); //debug-output 66 | return blur; 67 | } -------------------------------------------------------------------------------- /test_linearSampling/bw_test_motif_1080p_15s.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_linearSampling/bw_test_motif_1080p_15s.mp4 -------------------------------------------------------------------------------- /test_linearSampling/bw_test_motif_720p_rgb32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_linearSampling/bw_test_motif_720p_rgb32.png -------------------------------------------------------------------------------- /test_linearSampling/expected_result_mpv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_linearSampling/expected_result_mpv.png -------------------------------------------------------------------------------- /test_linearSampling/test_linearSampling1_motif.hlsl: -------------------------------------------------------------------------------- 1 | #define Red float4(1, 0, 0, 0) 2 | 3 | /* test_linearSampling1_motif (pass-1) 4 | Generates a black and white stripe test motif (8 pixels wide) 5 | 6 | use: 7 | PreResize=.\test_linearSampling1_motif;.\test_linearSampling2_result.hlsl; 8 | */ 9 | 10 | //sampler s0: register(s0); 11 | sampler s0 = sampler_state { 12 | MinFilter = Linear; 13 | MagFilter = Linear; 14 | MipFilter = Linear;//Point; 15 | AddressU = Clamp; 16 | }; 17 | float2 p0: register(c0); 18 | float2 p1: register(c1); //pixel width 19 | 20 | 21 | /* --- Main --- */ 22 | float4 main(float2 tex: TEXCOORD0): COLOR { 23 | 24 | /* in hlsl (vs glsl) texel centers are located mid-texel (first center: 0.5 pixels)*/ 25 | //if (tex.x < 0.4*p1.x) return Red; // no print instruction in hlsl, for testing the only output is the screen ! 26 | if (frac(tex.x*p0.x/16) <0.5) return 1; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test_linearSampling/test_linearSampling2_result.hlsl: -------------------------------------------------------------------------------- 1 | #define Offset_sampling 0.5 //0.5 is linear sampling offset, any value different from 0 should produce some interpolation. 2 | 3 | /* test_linearSampling2_result (pass-2) 4 | Linear sampling is a performance optimization exploited by some convolution kernel shaders (such as: LumaSharpen, gaussian blur, etc.). 5 | This test allows you to determine if it is working as expected. 6 | 7 | tested on mpc-hc v1.9.6 + EVR-CP, also tested on mpc-be 8 | on my setup (intel hd4400 igpu), I am seeing Nearest Neighbor (No interpolation) instead of Linear interpolation, with rounding artefacts for Offset_sampling 0.5 ! 9 | 10 | use: 11 | PreResize=.\test_linearSampling_motif;.\test_linearSampling_result.hlsl; 12 | */ 13 | 14 | // sampler s0: register(s0); 15 | sampler s0 = sampler_state { 16 | MinFilter = Linear; 17 | MagFilter = Linear; 18 | MipFilter = Linear;//Point; 19 | AddressU = Clamp; 20 | }; 21 | 22 | float2 p0: register(c0); 23 | float2 p1: register(c1); 24 | #define Red float4(1, 0, 0, 0) 25 | #define Green float4(0, 1, 0, 0) 26 | 27 | /* --- Main --- */ 28 | float4 main(float2 tex: TEXCOORD0): COLOR { 29 | // float4 res = lerp(tex2D(s0, tex), tex2D(s0, tex + float2(p1.x, 0)), Offset_sampling); 30 | float4 res = tex2D(s0, tex + p1*float2(Offset_sampling, 0)) ; 31 | if (abs(res.r-0.5)<0.001) return Green; // Expected interpolation for Offset_sampling 0.5 32 | if (res.r!=0 && res.r!=1) return Red; // otherwise, if there is any interpolation at all, you will see some red in output 33 | return res; 34 | } 35 | -------------------------------------------------------------------------------- /test_resize/pattern1_bw1080x1080.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_resize/pattern1_bw1080x1080.png -------------------------------------------------------------------------------- /test_resize/pattern1_bw18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_resize/pattern1_bw18.png -------------------------------------------------------------------------------- /test_resize/pattern1_bw180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/butterw/bShaders/d7c79b23b39a0f354faec5e9cb86901d7badc331/test_resize/pattern1_bw180x180.png --------------------------------------------------------------------------------