View Full Version : Video pixel shader pack


JanWillem32
26th October 2010, 05:58
Video pixel shader pack v1.4
Direct download link: http://www.mediafire.com/?025vsef8ads6t5x

YCbCr-type sharpen complex test 2
Direct download link: http://www.mediafire.com/?7vec9jyc8y861s9


For quite some time now, I've been developing pixel shaders for usage as image filters in video players.
Pixel shaders are basically small programs for the video card to transform images.
These pixel shaders are currently known to be compatible with KMPlayer, PotPlayer and MPC-HC.
If there are any flaws in the comments or code of the pixel shaders, please tell me. I'll happily correct items.
I intend to add new functions over time, so please suggest new filter types.


To make a pixel shader work in MPC-HC:
Depending on your OS and synchronization needs, select "VMR-9", "EVR Custom Pres." or "EVR Sync" in the "View">"Options">"Playback">"Output" menu. You can hover the mouse pointer over the different renderer options to get a description. Make sure that D3D fullscreen is disabled for the time being, you can activate it later on, when you've successfully enabled a shader.
Next, to enable a shader, right-click somewhere near the middle of a playing video, select "Shaders" and click on "invert" or some other shader that is really easy to test.
You might need to switch "Toggle Pixel Shaders" before a shader will work.
You can use multiple shaders in the "Combine Shaders..." or "Combine Screen Space Shaders..." menu. Not all shaders can be used in screen space mode.
Some shaders can't be used if your video card is old. View the comment about the pixel shader revisions in my shader to see wich video cards can use that shader.
Some shaders benefit greatly from enabling the the three "10-bit color" and "full floating point processing" options in "View">"Rendering Settings">"Presentation".

To add a new shader:
Tick "View">"Shader Editor".
Type in the name of a new shader in the long top left bar of the Shader Editor, to make the compiler write out a small, but useless script. Next, set the highest version pixel shader that your graphics card supports in the drop-down menu of the top right bar, avoid the software (sw) modes.
Remove all text from the main text box.
Copy the full text of a new shader and paste the text in the main text box.
If there's an error, the compiler will output an error code inside of the bottom message box. If all went well you will get a success message, the calculation chain will be displayed and the number of instructions used will be at the end of the text.
You can also use the drop-down menu from the top left bar to select and edit an already existing shader.

Tip: because I like to switch between shaders, but don't want to disable D3D Fullscreen I made a basic text batch file (.bat) to enable a certain shader. An example for activating "invert":
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "Shaders List" /D "invert|" /F
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "ShaderListScreenSpace" /D "" /F

To disable all active shaders:
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "Shaders List" /D "" /F
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "ShaderListScreenSpace" /D "" /F

To activate multiple shaders, separate the names by "|" (pipe), but also keep the one on the end.

Note: MPC-HC can't save larger shaders to the .INI settings files. Saving settings to the registry solves that problem.
If you want to make a copy of your settings from the registry:
- run regedit
- expand the tree to "HKEY_CURRENT_USER\Software\Gabest\Media Player Classic"
- right-click the "Media Player Classic" key
- click the export option
It produces an executable .REG file that you can use as a back-up or to transfer settings to another PC.

Directory listing:chroma interpolation
color controls
COPYING.txt
development
effect
gamma conversion for linear RGB
readme - how to properly chain shaders.txt
releaselog Video pixel shader pack v1.3.txt
resizer
sharpen
sharpen complex, deband and denoise
chroma interpolation\4÷2÷0 bilinear chroma filter and color controls for SD&HD video input.txt
chroma interpolation\4÷2÷2 bilinear chroma filter and color controls for SD&HD video input.txt
chroma interpolation\multi-pass
chroma interpolation\multi-pass\~4÷2÷0 content is up-sampled by a sequence of 1, 2 and 3
chroma interpolation\multi-pass\~4÷2÷2 content is up-sampled by a sequence of 1 and 3
chroma interpolation\multi-pass\1. RGB to Y'CbCr for SD&HD video input for floating point surfaces.txt
chroma interpolation\multi-pass\1. RGB to Y'CbCr for SD&HD video input for integer surfaces.txt
chroma interpolation\multi-pass\2. special 4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling.txt
chroma interpolation\multi-pass\2. special 4÷2÷0 to 4÷2÷2 intermediate cubic B-spline5 chroma up-sampling.txt
chroma interpolation\multi-pass\2. special 4÷2÷0 to 4÷2÷2 intermediate Mitchell-Netravali cubic5 chroma up-sampling.txt
chroma interpolation\multi-pass\3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling and color controls for floating point surfaces.txt
chroma interpolation\multi-pass\3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling and color controls for integer surfaces.txt
chroma interpolation\multi-pass\3. special 4÷2÷2 cubic B-spline5 chroma up-sampling and color controls for floating point surfaces.txt
chroma interpolation\multi-pass\3. special 4÷2÷2 cubic B-spline5 chroma up-sampling and color controls for integer surfaces.txt
chroma interpolation\multi-pass\3. special 4÷2÷2 Mitchell-Netravali cubic5 chroma up-sampling and color controls for floating point surfaces.txt
chroma interpolation\multi-pass\3. special 4÷2÷2 Mitchell-Netravali cubic5 chroma up-sampling and color controls for integer surfaces.txt
color controls\[16, 235], [16, 240], [16, 240] to full range for SD&HD video input.txt
color controls\brightness, contrast and gamma controls for RGB.txt
color controls\brightness, contrast, grayscale gamma, colorfulness gamma, hue and saturation controls for SD&HD video input.txt
color controls\full range to [16, 235], [16, 240], [16, 240] for SD&HD video output.txt
development\~interpolation methods, Catmull-Rom spline.txt
development\~interpolation methods, cubic B-spline.txt
development\~interpolation methods, Mitchell-Netravali cubic.txt
development\~standard Y'CbCr and RGB conversion codes.txt
development\3LCD panel horizontal software alignment, Catmull-Rom spline6 interpolated.txt
development\3LCD panel vertical software alignment, Catmull-Rom spline6 interpolated.txt
development\Catmull-Rom spline4×4 resizer (inefficient one-pass).txt
development\color gradients.txt
development\correct video colorspace BT.601 [SD] to BT.709 [HD] for HD video input.txt
development\correct video colorspace BT.709 [HD] to BT.601 [SD] for SD video input.txt
development\cubic B-spline4×4 resizer (inefficient one-pass).txt
development\deinterlace (blend).txt
development\detect BT.601 [SD] or BT.709 [HD].txt
development\detect even or odd coordinates, alternative.txt
development\detect even or odd coordinates.txt
development\draw grid coordinates.txt
development\flash every frame.txt
development\flash every second.txt
development\letterbox.txt
development\Mitchell-Netravali cubic4×4 resizer (inefficient one-pass).txt
development\pillarbox.txt
development\RGB to Y'CbCr for SD&HD video input for floating point surfaces.txt
development\RGB to Y'CbCr for SD&HD video input for integer surfaces.txt
development\Y'CbCr to HD&SD video RGB output for floating point surfaces.txt
development\Y'CbCr to HD&SD video RGB output for integer surfaces.txt
effect\chroma for SD&HD video input.txt
effect\color gate for RGB.txt
effect\color gate for SD&HD video input.txt
effect\color gate inverse for RGB.txt
effect\color gate inverse for SD&HD video input.txt
effect\contour color expose banding.txt
effect\contour color.txt
effect\contour monochrome.txt
effect\emboss.txt
effect\flip and rotate sampling direction for RGB.txt
effect\grayscale for RGB.txt
effect\grayscale for SD&HD video input.txt
effect\invert.txt
effect\nightvision.txt
effect\projector film drive scratches.txt
effect\projector film dust.txt
effect\projector film lamp vignette.txt
effect\projector film sepia toning for SD&HD video input.txt
effect\projector film shaking.txt
effect\semi-random colored surface noise.txt
effect\semi-random grayscale noise.txt
effect\sphere, Catmull-Rom spline4×4 interpolated.txt
effect\spotlight.txt
effect\wave, Catmull-Rom spline4×4 interpolated.txt
gamma conversion for linear RGB\gamma conversion of linear RGB to video RGB for floating point surfaces.txt
gamma conversion for linear RGB\gamma conversion of linear RGB to video RGB for integer surfaces.txt
gamma conversion for linear RGB\gamma conversion of linear RGB to wide gamut RGB for floating point surfaces.txt
gamma conversion for linear RGB\gamma conversion of linear RGB to wide gamut RGB for integer surfaces.txt
gamma conversion for linear RGB\gamma conversion of video RGB to linear RGB for floating point surfaces.txt
gamma conversion for linear RGB\gamma conversion of video RGB to linear RGB for integer surfaces.txt
resizer\Catmull-Rom spline4 height resizer.txt
resizer\Catmull-Rom spline4 width resizer.txt
resizer\Catmull-Rom spline5 height doubler.txt
resizer\Catmull-Rom spline5 width doubler.txt
resizer\Catmull-Rom spline6 height resizer.txt
resizer\Catmull-Rom spline6 width resizer.txt
resizer\cubic B-spline4 height resizer.txt
resizer\cubic B-spline4 width resizer.txt
resizer\cubic B-spline5 height doubler.txt
resizer\cubic B-spline5 width doubler.txt
resizer\cubic B-spline6 height resizer.txt
resizer\cubic B-spline6 width resizer.txt
resizer\Mitchell-Netravali cubic4 height resizer.txt
resizer\Mitchell-Netravali cubic4 width resizer.txt
resizer\Mitchell-Netravali cubic5 height doubler.txt
resizer\Mitchell-Netravali cubic5 width doubler.txt
resizer\Mitchell-Netravali cubic6 height resizer.txt
resizer\Mitchell-Netravali cubic6 width resizer.txt
resizer\Perlin Smootherstep2×2 resizer.txt
sharpen\sharpen.txt
sharpen\unsharp luma mask for SD&HD video.txt
sharpen complex, deband and denoise\~the r=6 types are the most complex, the r=1 types the least
sharpen complex, deband and denoise\r=1 blur.txt
sharpen complex, deband and denoise\r=1, sharpen complex, deband and extreme denoise.txt
sharpen complex, deband and denoise\r=1, sharpen complex, deband and heavy denoise.txt
sharpen complex, deband and denoise\r=1, sharpen complex, deband and medium denoise.txt
sharpen complex, deband and denoise\r=1, sharpen complex, deband and mild denoise.txt
sharpen complex, deband and denoise\r=1, sharpen complex, deband and minimal denoise.txt
sharpen complex, deband and denoise\r=1, sharpen edge complex, deband and extreme denoise.txt
sharpen complex, deband and denoise\r=1, sharpen edge complex, deband and heavy denoise.txt
sharpen complex, deband and denoise\r=1, sharpen edge complex, deband and medium denoise.txt
sharpen complex, deband and denoise\r=1, sharpen edge complex, deband and mild denoise.txt
sharpen complex, deband and denoise\r=1, sharpen edge complex, deband and minimal denoise.txt
sharpen complex, deband and denoise\r=2 blur.txt
sharpen complex, deband and denoise\r=2, sharpen complex, deband and extreme denoise.txt
sharpen complex, deband and denoise\r=2, sharpen complex, deband and heavy denoise.txt
sharpen complex, deband and denoise\r=2, sharpen complex, deband and medium denoise.txt
sharpen complex, deband and denoise\r=2, sharpen complex, deband and mild denoise.txt
sharpen complex, deband and denoise\r=2, sharpen complex, deband and minimal denoise.txt
sharpen complex, deband and denoise\r=3 blur.txt
sharpen complex, deband and denoise\r=3, sharpen complex, deband and extreme denoise.txt
sharpen complex, deband and denoise\r=3, sharpen complex, deband and heavy denoise.txt
sharpen complex, deband and denoise\r=3, sharpen complex, deband and medium denoise.txt
sharpen complex, deband and denoise\r=3, sharpen complex, deband and mild denoise.txt
sharpen complex, deband and denoise\r=3, sharpen complex, deband and minimal denoise.txt
sharpen complex, deband and denoise\r=4 blur.txt
sharpen complex, deband and denoise\r=4, sharpen complex, deband and extreme denoise.txt
sharpen complex, deband and denoise\r=4, sharpen complex, deband and heavy denoise.txt
sharpen complex, deband and denoise\r=4, sharpen complex, deband and medium denoise.txt
sharpen complex, deband and denoise\r=4, sharpen complex, deband and mild denoise.txt
sharpen complex, deband and denoise\r=4, sharpen complex, deband and minimal denoise.txt
sharpen complex, deband and denoise\r=5 blur.txt
sharpen complex, deband and denoise\r=5, sharpen complex, deband and extreme denoise.txt
sharpen complex, deband and denoise\r=5, sharpen complex, deband and heavy denoise.txt
sharpen complex, deband and denoise\r=5, sharpen complex, deband and medium denoise.txt
sharpen complex, deband and denoise\r=5, sharpen complex, deband and mild denoise.txt
sharpen complex, deband and denoise\r=5, sharpen complex, deband and minimal denoise.txt
sharpen complex, deband and denoise\r=6 blur.txt
sharpen complex, deband and denoise\r=6, sharpen complex, deband and extreme denoise.txt
sharpen complex, deband and denoise\r=6, sharpen complex, deband and heavy denoise.txt
sharpen complex, deband and denoise\r=6, sharpen complex, deband and medium denoise.txt
sharpen complex, deband and denoise\r=6, sharpen complex, deband and mild denoise.txt
sharpen complex, deband and denoise\r=6, sharpen complex, deband and minimal denoise.txt

toniash
2nd November 2010, 17:19
I'm interested in trying new shaders, could you send me them?
Thanks, toni

burfadel
2nd November 2010, 19:19
I'd be interested in having a look at them too. The upsampling shaders demonstrated in the attached images look interesting, I'd like to see how they'd look on a more detailed scene. I think when combined with a nice sharpening effect like 'sharpen complex 2' they'd look especially good...

Here's a question though...
How is the work distributed on the shaders? Does it use few shaders but intensely, or divide up the image into areas and distribute the work to the shaders that way (and hence use them lightly)?

tetsuo55
3rd November 2010, 11:57
Hello and thanks for sharing this.

I will try to answer your questions:

1. All the code and comments should be in english, since most of our stuff is hosted in the US their english probably works best.

2. The Shaders should use GPU as efficiently as possible, but those that are very heavy might be marked as such.
Don't compromise quality over speed unless you have to.

leeperry
3rd November 2010, 15:26
the PS scripts also work in KMPlayer and PotPlayer btw ;)

english seems the best choice indeed.

JanWillem32
4th November 2010, 01:05
Thank you for your input, I've been busy improving my shaders (including procamp). It took a lot of effort to get the two "4÷2÷0 Chroma Up-sampling&16-235 To 0-255" shaders to work with the 64 instructions limit for ps_2_0.

@toniash; Very well, I attached almost everything I currently have.
@burfadel; Pixel shaders work by taking one pixel of a new, empty frame and construct it pixel-by-pixel by sampling and processing pixels from an original frame. An output frame size of 1920×1080 pixels will execute the same pixel shader 1920×1080 = 2,073,600 times. It is even more times if your pixel shader samples multiple pixels per execution, when stacked with another pixel shader, see my little test at the end of this post. Secondly, I added chroma sharpen to the pixel shader and I made a hybrid that combines chroma 4:2:0 up-sampling, chroma sharpen, sharpen complex and deband. The attached screenshot is not the best representation of what the hybrid shader usually does, but indeed, sharpening does work. I will search for a better example.
@tetsuo55; I commented everything in US English and increased efficiency quite a bit for a few shaders.
@leeperry; Nice to know that other programs can use this type of shaders too, I will see to it that the comments will not be program-specific.


These shaders should really be deleted.

0-255 -> 16-235; The chroma values are not compressed properly and it can not be used with input bitdepths higher than 8-bit.
16-235 -> 0-255; [SD] Applying expansion only to BT.601 [SD] material is wrong, as BT.709 [HD] is limited to "16-235" as well, the only full range YUV colorspaces are: JPEG (most variants), Digital Cinema (JPEG2000 variant), FRAPS video and many studio formats.
16-235 -> 0-255 [SD][HD]; The chroma values are not expanded properly and it can not be used with input bitdepths higher than 8-bit.
BT.601 -> BT.709; The colorspaces are calculated with truncated decimal fractions, the SD/HD detection rule is wrong for video with a resolution of 1280×533, aspect ratio 1/2.40.
grayscale; Uses a BT.601 [SD] colorspace, so the name is wrong.
procamp; Uses a BT.601 [SD] colorspace with truncated decimal fractions.
YV12 Chroma Upsampling; Uses a BT.601 [SD] colorspace with truncated decimal fractions, even worse, the method is wrong, see images for reference.

Note: ">" can not be used for filenames in NTFS, FAT32 or exFAT filesystems. When saving a shader in a text file, it is often preferred to name the file the same way as the title of the shader, so avoid using the "forbidden" characters in the titles for shaders.


I measured the GPU usage for video playback with two of my shaders and compared it to other modes.

Video card: ATi Radeon HD4890 at 600 MHz GPU clock and 975 MHz memory clock (forced clockspeeds in ATi Tray Tools)
Display: Compaq P1220 CRT, D-Sub analog, 2048×1536, 80Hz
Software: Windows 7 Home Premium x64, ATi Catalyst 10.5a (the last version capable of 10-bit RGB output from DXVA, the driver does not up-sample down-sampled chroma in 10-bit RGB mode), ATi Tray Tools v1.6.9.1486 (for measuring), MPC-HC x64 v1.4.2667.0
Rendering: Aero enabled, internal H264/AVC DXVA decoder, EVR-CP, no advanced features of ATi Catalyst (they do not work in 10-bit RGB mode anyway, exept for Denoise)
EVR-CP rendering options: Output Range 0-255, 10-bit RGB Output, Force 10-bit RGB Input, Full Floating Point Processsing, Enable Frame Time Correction, color Management Enabled (with a recently made system-wide color profile), VSync disabled, Flush GPU after Present.
Video source: Blu-ray of the movie "Avatar" (without subtitles), H.264/AVC/MPEG 4 part 10 codec, 4:2:0 chroma subsampling, 8-bit per component YUV. (Quite a shame, the main feature file almost fills up the entire 50 GB of the disk, but it does not use 4:4:4 (no subsampling of chroma) with at least 10-bit per component YUV, like the Digital Cinema version.)

Measurement of peak GPU usage after 5 seconds of video (when the frame rate remains stable)
87.65%; render with "4÷2÷0 Chroma Up-sampling BT.709 [HD]" and "Sharpen Complex v3 + Deband"
54.08%; render with "Sharpen Complex v3 + Deband"
10.04%; render with "4÷2÷0 Chroma Up-sampling BT.709 [HD]"
08.71%; render without shaders
02.20%; MPC-HC not loaded, system almost idle
86.03%; render with "4÷2÷0 Chroma Up-sampling BT.709 [HD]" and "Sharpen Complex v3 + Deband" in D3D Fullscreen Mode
67.86%; render with an experimental hybrid shader of "4÷2÷0 Chroma Up-sampling BT.709 [HD]" and "Sharpen Complex v3 + Deband" in D3D Fullscreen Mode

Processing pixel shaders in ps_3_sw or ps_2_sw (CPU software mode) failed.
I could not detect any changes in peak or average GPU usage between rendering in ps_2_0 and in ps_3_0 modes for the "4÷2÷0 Chroma Up-sampling BT.709 [HD]" shader.
When stacking any pixel before "Sharpen Complex v3 + Deband", that pixel shader is used on all 177 input pixels, for every pixel the "Sharpen Complex v3 + Deband" shader is used on. This method is rather inefficient when combining heavy shaders. Does anyone know a solution to this problem? (Like using a buffer frame in-between shaders or something, if possible.)
The experimental hybrid shader does not output the same thing as the two shaders combined. It only up-samples the current pixel it is working on, not the surrounding pixels, unfortunately.

clsid
4th November 2010, 01:22
16-235 -> 0-255; [SD] Applying expansion only to BT.601 [SD] material is wrong, as BT.709 [HD] is limited to "16-235" as well, the only full range YUV colorspaces are: JPEG (most variants), Digital Cinema (JPEG2000 variant), FRAPS video and many studio formats.This shader is intended for situations were the decoder/renderer/driver doesn't do the correct expansion. They are not for general use with a properly functioning playback chain. For example, some ATI drivers mess up, but only at SD resolutions. Hence, the "[SD]" part, which simply means the shader only operates on videos with SD resolution.

leeperry
4th November 2010, 08:59
YV12 Chroma Upsampling; Uses a BT.601 [SD] colorspace with truncated decimal fractions, even worse, the method is wrong, see images for reference.

OK, interesting! That might give some more room for comparisons against madVR :)

JanWillem32
4th November 2010, 14:20
@clsid How old are the drivers that only mess up luma/chroma expansion of SD content (without messing up de-blocking, de-ringing, chroma up-sampling, colorspace, etcetera)? I Know that 10.4, 10.5 and 10.5a totally mess up SD playback, but I never noticed wrong output levels on SD content even with older drivers. Enabling "16-235 To 0-255 BT.601 [SD]" will provide proper expansion by the way, but I did not include an auto-detect function for SD/HD. If there are more problems than only luma/chroma expansion, I can make a hybrid of a few shaders to correct all of those problems.
@leeperry I certainly hope so.

clsid
4th November 2010, 20:43
The problem only occurs with some of the video renderers. Most notably with VMR-9 (renderless).

CiNcH
6th November 2010, 12:55
Can some mod approve those downloads please?

Virtual_ManPL
6th November 2010, 13:10
Or simply upload it to MediaFire (http://www.mediafire.com/)

burfadel
6th November 2010, 19:21
Particularly 'Sharpen Complex v3 + Deband' and 4÷2÷2 Chroma Up-sampling BT.601 [SD] :)

What difference would using the shader editor and setting them as PS 3.0 instead of PS 2.0? If they fairly intensive and require a non-ancient GPU, then PS 3.0 should be fine... Even PS 3.0 is ancient by todays standards.

JanWillem32
6th November 2010, 22:19
@clsid I could not find a more recent entry than 2008, when a few driver versions had the "UseBT601CSC" registry entry on "0", instead of "1". The correct solution is to install a recent driver (even the legacy hardware driver is at 10.2), or switch "UseBT601CSC" on (with DXVA checker or regedit). Unless a new driver comes out with this problem, it would be best to get rid of the "16-235 -> 0-255 [SD]" shader. It is inaccurate too by the way: The chroma values are not expanded properly, it can not be used with input bitdepths higher than 8-bit and the SD/HD detection rule is wrong for video with a resolution of 1280×533, aspect ratio 1/2.40.

@burfadel compiler message at the end of compiling: 4÷2÷2 Chroma Up-sampling&16-235 To 0-255 BT.601 [SD]:
ps_2_0: error X5608: Compiled shader code uses too many arithmetic instruction slots (86). Max. allowed by the target (ps_2_0) is 64.
ps_2_a: // approximately 62 instruction slots used (6 texture, 56 arithmetic)
ps_3_0: // approximately 55 instruction slots used (6 texture, 49 arithmetic)

For some reason PS 2.0 is really inefficient when dealing with this code (it's about the same with all other shaders, too).
Sharpen Complex v3 + Deband is very demanding (the hybrid shader is even more complex):
ps_2_0: error X5426: Shader uses texture addressing operations in a dependency chain that is too complex for the target shader model (ps_2_0) to handle. & error X4505: maximum temp register index exceeded
ps_2_a: error X4505: maximum temp register index exceeded
ps_3_0: // approximately 917 instruction slots used (177 texture, 740 arithmetic)

I'm not even going to try to fit that into a PS 2.0a version. I did make the "4÷2÷0 Chroma Up-sampling&16-235 To 0-255" shaders simple enough to be run by PS 2.0 (for ancient hardware).
To answer your question: shader code is handled more more efficiently by newer versions because the compiler can use more kinds of instructions to feed to the processor.
Secondly, PS 2.0 has an arithmetic instruction limit of only 64. As you can see with my first example, a simple shader like this only needs 49, if compiled with reasonably modern processing code. I can look up what a DX11 compiler does with the code, by the way. It will probably use even less instructions. I wonder if picture scaling with PS 3.0 could be implemented besides the PS 2.0 versions, it would probably be more efficient.

I added a newer version of Sharpen Complex v3 + Deband that doesn't produce as much staircase artifacts as my first test version. It looks okay on 1080p scenes even with extremely sharp contrasts, but artifacts are still too visible on lower input video resolutions. The power factor to balance the sharpening on extremely sharp contrasts is not perfect yet, maybe someone can think of something to balance it a bit better.
Running the shader in screen space isn't possible for my setup, my GPU can't execute this shader at 80 Hz (and it would be inefficient to do that with 24 fps input video). I would like to know if it's possible to execute a shader on textures that are scaled to the display resolution, but are not locked to the screen refresh rate.

@CiNcH This topic really needs to draw a bit more attention, indeed. It has been days since I posted those shaders and a picture. What kind of vulgar ASCII art do members of this forum put inside textfiles to demand that a mod has to approve attached textfiles of 13 KB or less?

nurbs
6th November 2010, 22:36
What does Sharpen Complex actually do? I mean it obviously sharpens, but what about the complex part of the name? Since your version is v3 how is that different from what comes with MPC-HC now?

CiNcH
6th November 2010, 22:39
What does "UseBT601CSC" actually do? Does it transform SD to BT.709? Or HD to BT.601?

JanWillem32
7th November 2010, 04:54
@nurbs I wanted a shader that can deband. The approach was easy: analyze if the surrounding areas are nearly the same and then blur the pixel with the surrounding areas. Because that analysis also tells you if the pixel is on a contour or in a detailed area, it is very easy to implement sharpen too. I re-used a lot of code from sharpen complex v2 for the sharpen part. They were easy to combine, and the sharpen part can be disabled by setting the amount of sharpen coefficients to 0. That doesn't lower the processing requirements a lot however.
The complex part is that it first analyses the surrounding pixels, and then uses a mechanism that increases (or decreases) the contrast of the pixel that the shader is working on. My shader uses 6 different methods to either blur or sharpen, depending on the contrast with the surrounding zones.
I know that this shader is a bit "future orientated", but with the very fast increase in GPU power over the years, I don't mind making a heavy shader.
The shader is still beta, it could use some more blur and sharpen methods and it really needs some fine-tuning of the sharpening adaptation to the relative contrast. At the moment it is okay for 1080p, but only so-so for 720p, unless I upscale it to the display resolution first.

@CiNcH "UseBT601CSC" tells the GPU driver to convert limited range YUV <16,235> for Y (luma), <16,240> for U and V (chroma), to full-range YUV when enabled (<0,255> in 8-bit or normalized <0,256> for higher bitdepths), or to do no conversion when disabled. When luma is not expanded, a converted full-range RGB picture will have a dark gray tint instead of black, and a light gray tint instead of white. When Chroma is not expanded, colors can not become saturated, and the whole picture will be dull.

nurbs
7th November 2010, 08:31
Thank you for the explanation.

tetsuo55
7th November 2010, 19:31
hey JanWillem32 could you explain why we need all the different, nearly the same name shaders?

don't we all just want to:

Chroma upscale, luma upscale, expand(or compress), deband, denoise and sharpen?

burfadel
7th November 2010, 22:11
I add noise through ffdshow, not remove it! lol. Not on default settings though, no chroma and reduce the luma noise down, deprending on resolution. Since the noise is fine and non-chroma, it actually seems to improve picture quality when you're not too close to the screen :)

I'm guessing you mean encoded noise though, which is different as noise doesn't encode (and hence decode) too well and there's a lot more of it!

JanWillem32
7th November 2010, 22:38
@tetsuo55 I can give all shaders that are dependant on input of BT.709 [HD] or BT.601 [SD] YUV primary's an auto-detect function to combine the two. But that will add to the complexity, so many shaders will at least become PS 2.0a versions. If you switch them manually for SD or HD input, most of them will be PS 2.0 minimum. Secondly, some shaders are dependant on the display output calibration, if we assume a full-range display output with sRGB or BT.709 [HD] colors (their primary's are the same), some BT.601 [SD] shaders can be removed. Lastly, the combined shaders (exept for the hybrid) are for older machines with problems with both chroma up-sampling and luma/chroma expansion. The combination of both is quite common, and the shader functions are easy to combine with very little processing. It could be confusing for some people how to use them, however.
What do others think about reducing the number of shaders by: combining video input-type HD and SD versions, removing display output-type SD versions and removing chroma up-sampling & luma/chroma expansion combination-type shaders?

@burfadel Most GPU DXVA driver parts support denoise on output, else there's a denoise shader (which blurs a lot by the way). It's required to do sharpening and debanding effectively on VERY noisy pictures, else everything would be horribly sharpened.
The original reason I made a debanding shader is because I absolutely hate the almost-8-bit dithering and lossy compression artifacts that are present in all my videos. Having a noisy output is your personal preference, I personally hate it if they use a cheap tape to master a blu-ray release, instead of a digital master, or even a cleaned up version of an old tape. I always get the feeling that I'm looking at a rotten old TV, instead of what my projector is capable of (or even my CRT monitor, for that matter).
Sharpen Complex v3 + Deband is rendered in pure 1:1:1 RGB, by the way, so it's not very dependent on chroma and luma. I have tried to use YUV for this shader, but the outcome was ugly.

burfadel
8th November 2010, 00:25
I don't mean the levels of noise they put on some blu-rays, just a tiny amount of clean fine luma noise, set in ffdshow as 'mplayer noise', pattern, average, no chroma, and a little luma noise (say 8). The default settings give the completely wrong effect. The idea is so the noise isn't visible at the viewing distance (or barely perceptible), which seems to bring out some details better and seems to hide some small artifacts. If set incorrectly it definitely has the opposite effect!

JanWillem32
8th November 2010, 01:30
I really have to ask: is your display even capable of at least 10 bit output with at least the complete sRGB color range? The method you describe is quite close to the standard temporal dithering method, a common method to try to generate in-between colors by switching the somewhat slow LCD crystals constantly in between two shades.

CiNcH
8th November 2010, 09:40
Hi Jan,

Got two more questions. Hope you can answer them for me.

I am experiencing the bad chroma upsampling with my ATi/AMD. Is it really due to ATi? I am only seeing it with the Custom Presenter, but not with standard EVR for example. Is standard EVR performing a better chroma upsampling within shaders already? Or is the bad chroma upsampling solely a problem of the Custom Presenter implementation? It does not seem to affect nVIDIA though. *confused*

So if the source is 16..235 and the display is 16..235, why do we have to intermediary convert it to 0..255? Can renderers only work in full RGB?

tetsuo55
8th November 2010, 11:15
hi JanWillem32, anything that can be automated is a good thing imho, even if it bumps up the required shader version a bit.

But we should still support different output colorspaces etc..

@CiNcH, that is highly interesting.. maybe its a bug in mpc-hc then?

CiNcH
8th November 2010, 13:17
@CiNcH, that is highly interesting.. maybe its a bug in mpc-hc then?
I just did another test to verify my above statement as it was based on tests I conducted some time ago.

I now used MPC-HC 1.4.2703 and 'CyberLink Video/SP Decoder' (to take advantage of DXVA for MPEG-2). GPU is an ATi Radeon HD 3650 with up-to-date driver.

Standard EVR: proper chroma upsampling
http://data6.blog.de/media/127/5113127_584572f62c_l.jpeg

Custom Presenter for EVR: bad chroma upsampling
http://data6.blog.de/media/126/5113126_bf11674fec_l.jpeg

JanWillem32
8th November 2010, 19:03
@CiNcH I have the same problem, and it is a very common problem, too. The ATi drivers currently can output 10-bit color, but can't up-sample chroma while doing so. It's not a great loss, however. The driver only does a blurry bi-cubic up-sampling at best (you can test it using my chroma shaders). My up-sampling shader uses a different method based on 2× magnification, the output is less blurry and on top of that, it can sharpen the chroma with a basic unsharp mask filter (more advanced methods did not increase sharpening quality much).
YUV <16,235> to any RGB conversion is a bit lossy, so if the RGB range is only <16,235>, floating points get truncated more than with a range of <0,255>. When you go beyond the 8-bit problem and process in a good floating point format, this is less of a problem. Secondly there is a difference beween RGB with a range of <16,235> with expanded chroma and without, to make things even more difficult. Third, limited range YUV was made to handle old analog TV. Limited-range RGB is an odd format, even analog D-sub connections don't use it. Limited range YUV is a really old format, and in my opinion they should never accepted any compatibility between SD and HD colorspaces. HD only has a colorspace equal to sRGB. The odd thing is, The colorspace of the Digital Cinema format (that was made before BT.709 [HD]) covers the complete CIE 1931 color space, and uses a variant of full range YUV, that is in my opinion the proper way of handling things. The problem with Digital Cinema is that it's completely incompatible with BT.601 [SD] without some serious conversion work, that's why the format was rejected for HD, unfortunately.

@tetsuo55 I will write a complete new set of shaders, then.

For those that are wondering what the chroma up-sampling error is, the wikipedia article about it is quite good. http://en.wikipedia.org/wiki/Chroma_subsampling

clsid
9th November 2010, 17:39
Is there much performance difference when a shader supports multiple bitdepths compared to just one (8bits)? Since some people with slightly older cards already often have performance issues with some of the current shaders, it might be worthwhile to create separate shaders for the two bitdepths that MPC currently supports (8 and 10). Since you mentioned accuracy a few times, it might also be useful to have both accurate and faster less accurate versions of some of the shaders. Just an idea, since I don't know what the performance difference might be.

JanWillem32
10th November 2010, 03:56
The difference between full range (floating point <0,1>) and 8-bit (integers only <0,255>) is at its top white value a bit less than .4 %. It depends on how the display chain is configured, but it is hard to guess how a system compensates for the white levels that 8-bit color can't use, while the processing format allows full range. So, to be at least accurate for the floating point range, I made the shaders without compensation. I think that making separate shaders for various bit-depths can also be quite confusing for people, especially since there is a difference between how to handle 10-bit input, processing and output.
When it comes to accuracy, that comes for free. The compiler will convert any incoming floating-point number to a 64-bit floating point number, the native format. If you feed it a decimal number truncated to three digits after the point, it will not output the same thing as when you give the exact calculation to the compiler. As an example: .333 is not exactly the same as 1/3. Whichever number of the two you use does affect quality, but doesn't increase complexity in the execution stage (after the compiling is done). On the other hand, the "4÷2÷0 chroma up-sampling for SD&HD video input" shaders require PS 2.0a, while the versions without detection require PS 2.0. That's why I included those four versions for older machines that can't do PS 2.0a.
The automatic detection was very easy, because the compiler is very forgiving on having the same code with different numbers entered for SD and HD. All YUV shaders can't be used in screen space anymore, because the detection needs to sample the input resolution.

tetsuo55
10th November 2010, 09:59
According to wikipedia (http://en.wikipedia.org/wiki/Pixel_shader) PS2.0a is support is:

Nvidia: All cards since 2003
ATI: All cards since 2004
Intel: All cards since 2006 (i highly doubt it actually works correctly though)

Most people won't have an intel card in their HTPC, but the intel cards are very popular so there is a risk in supporting only PS2.0a.

I talked to someone in the past who said pixel shaders could be written to be shader version agnostic. The code in mpc-hc would be changed to support these kinds of shaders and automatically select the highest PS version available. At the cost of losing support for 1.4 and lower

CiNcH
10th November 2010, 12:39
I just created a ticket with the MPC-HC support system concerning the bad chroma upsampling with custom presenters + ATi.

clsid
10th November 2010, 14:55
@JanWillem32
Good to hear that performance is not an issue. That certainly makes life easier.

Would it be possible to do the following?
- Detect the highest shader model supported by the card.
- Use the detected version for all shaders. I assume they are backwards compatible, and that higher versions are at least as fast as lower ones.
- The version currently set for each shader serves as a minimum requirement for that shader. When the detected max version is lower than the minimum of a shader, that shader should be disabled (grayed out, or hidden) in the menu.

JanWillem32
10th November 2010, 16:32
@tetsuo55 Making the shaders shader version agnostic is not an option for the heavier shaders, because of the 64 instructions limit. That limit is very low, and even if some instructions are skipped, such as with the selector for SD/HD, they still count.
By the way, the YV12 upsampler that is currently present uses 9 texture, 56 arithmetic instructions on PS 2.0, 9 texture, 45 arithmetic instructions on PS 3.0.
"4÷2÷0 chroma up-sampling for SD video input on old PS 2.0 hardware" uses 4 texture, 63 arithmetic instructions on PS 2.0 with sharpening, 4 texture, 51 arithmetic instructions on PS 2.0 without sharpening (they are mostly simple calculations, the YUV-RGB conversion is much more complex), 4 texture, 33 arithmetic instructions on PS 3.0 with sharpening and 4 texture, 24 arithmetic instructions on PS 3.0 without sharpening.
This doesn't tell exactly how well a shader performs, but I did take the effort to make it scale well on different PS versions.

@clsid That sounds very good, indeed.

toniash
10th November 2010, 17:12
do you know this shader? ->

// SuperResolution720p - Beta3
// Emmanuel - 31/03/2010
// Filtre de super résolution adapté aux diffuseurs 720p
// Ce filtre est conçu comme un filtre de post-traitement d'un
// filtre de sharpen tel que le filtre "unsharp mask" de ffdshow

#define FinesseRendu 0 // 0: très fin, 1: fin, 2: moyen, 3: grossier

#define SeuilBruit 0.15 // pour éviter la remontée du bruit de fond et
// l'accentuation de petits détails dans les textures
// Entre 0.1 et 0.2

#define diff 0.49 // influe sur le rendu "3D-Like"
// Après unsharp mask à 19 dans ffdshow:
// 0.49 => 3D-Like + présent
// 0.50 => 3D-Like présent
// 0.51 => 3D-Like - présent

sampler s0 : register(s0);
float4 p1 : register(c1);

#define dx (p1[0])
#define dy (p1[1])

float4 main( float2 tex : TEXCOORD0 ) : COLOR
{
// pixels original, flouté, corrigé
float4 ori = tex2D(s0, tex);
float4 flou;
float4 cori;
float seuil = 0.82 + FinesseRendu/100;

// récupération de la matrice de 9 points
// [ 1, 2 , 3 ]
// [ 4,ori, 5 ]
// [ 6, 7 , 8 ]

float4 c1 = tex2D(s0, tex + float2(-dx,-dy));
float4 c2 = tex2D(s0, tex + float2(0,-dy));
float4 c3 = tex2D(s0, tex + float2(dx,-dy));
float4 c4 = tex2D(s0, tex + float2(-dx,0));
float4 c5 = tex2D(s0, tex + float2(dx,0));
float4 c6 = tex2D(s0, tex + float2(-dx,dy));
float4 c7 = tex2D(s0, tex + float2(0,dy));
float4 c8 = tex2D(s0, tex + float2(dx,dy));

// détection des contours
// par filtre de sobel
float delta1,delta2,value;

// Gradient horizontal
// [ -1, 0 ,1 ]
// [ -2, 0, 2 ]
// [ -1, 0 ,1 ]
delta1 = (c3 + 2*c5 + c8)-(c1 + 2*c4 + c6);

// Gradient vertical
// [ -1,- 2,-1 ]
// [ 0, 0, 0 ]
// [ 1, 2, 1 ]
delta2 = (c6 + 2*c7 + c8)-(c1 + 2*c2 + c3);

// calcul
value = sqrt(mul(delta1,delta1) + mul(delta2,delta2)) ;

// Gamma adaptatif à proximité d'une transition
cori = ori;
if ((value >= seuil-diff*1.15)&&(value <= seuil)) cori = pow(ori,1./(1-value/10));

// Masque flou pour renforcer les textures

// calcul image floue (filtre gaussien)
// pour normaliser les valeurs, il faut diviser par la somme des coef
// 1/(1+2+1+2+4+2+1+2+1) = 1/ 16 = .0625

flou = (c1+c3+c6+c8 + 2*(c2+c4+c5+c7)+ 4*cori)*0.0625;

// Accentuation des textures si on est loin d'un bord
if ((value > SeuilBruit) && (value < seuil-diff)) cori = 2*cori - flou;

return cori;
}

Virtual_ManPL
10th November 2010, 20:23
It's just me or MPC-HC didn't remember saved shaders like for example "test 3, sharpen complex v3 + deband.txt" ?
And nice will be creating standalone shaders instead of fusioned ones

JanWillem32
10th November 2010, 21:24
@toniash It looks like a variant on virtualdub's warp resize, maybe a bit heavier. Personally, I would have decomposed the float4 values completely, to avoid the "calcul" part. There are easier ways to determine the contrast between the current pixel and the surrounding ones. For "detection of primary contours" in "test 3, sharpen complex v3 + deband", 16 absolute contrast values and 7 derived minimum/maximum contrast values are determined without much processing. Else, it's a nice resizer, bit it will be very sensitive to over-sharpening on grainy images, because the sampling area is only 9 pixels.
@Virtual_ManPL MPC-HC can't save larger shaders to .INI files, I believe someone already made a bug report about it. Does saving to the registry solve your problem?
For the standalone shaders, I agree with you, If you don't watch either SD or HD, or if you don't mind switching them manually, you don't need a combined SD/HD shader. It saves two instructions per pixel when processing. For the less advanced user, the automatic switching functions are a lot easier.

Virtual_ManPL
10th November 2010, 21:53
It saves two instructions per pixel when processing.
Awww... nice :)
So I will rechange my shaders then

JanWillem32
11th November 2010, 04:38
I just analyzed the Windows Color System, my choice to not correct for the limitations of the <0,255> or <0,1023> range versus the floating-point range was right. The Windows color system reserves 1/256 and 1/1024 above the highest integer by default with 8-bit and 10-bit color systems respectively, unless the LUT in the monitor color profile tells it to do otherwise. Logo CalibrationTester tells me the same thing, too. Just to be sure, does MPC-HC input the unmodified floating-point output from the shaders to the LUT in the monitor color profile?
The sharpening settings for test 3, sharpen complex v3 + deband are high, .375&.1875 or even lower towards .25&.125, are less over-sharpening for images with at least decent quality. It's too bad that almost all improvements I tried to implement in the test 4 version makes it too complex for PS 3.0, it will only compile for DX10/11. It has a better fine gradient and border detection filter that makes it more accurate without sampling more pixels, so I will store it for the future. Right now I'm trying to find a good set of values and possibly a method of balancing for the optimal blur&sharpen coefficients in a "final" version of "sharpen complex v3 + deband" based on test 3. Does anyone have a good idea? :confused:

@Virtual_ManPL As long as you are happy with me keeping you busy. :)

Mercury_22
11th November 2010, 11:58
@JanWillem32

The fact that since Revision 1826 - Directory Listing
Modified Sun May 2 01:20:06 2010 UTC (4 months, 1 week ago) by kinddragon

DX7 presenters splitter to several files
Improved Reset() handling (ticket #12) 10-bit RGB mode (Display A2R10G10B10) it's NOT working anymore isn't affecting your shaders ?

JanWillem32
12th November 2010, 00:47
That really doesn't matter as long as the floating point range <0,1> is correctly mapped to 8-bit integer <0,256>, with the top value removed. In other words, the floating point 255/265 should be exactly mapped to the 8-bit integer 255. Of course, the LUT in the color profile may change that to a non-default output value. My projector is reporting 10-bit input by the way, but that could very well be just the driver converting 8-bit values with the color profile and outputting 10-bit. Even with a complete blur shader on a minimal transition gradient sky, I can easily see banding. I don't have ultra-sensitive eyes, so if that's 10-bit color, it isn't very good. It's the same problem on the CRT.
After closing a video with Aero and D3D fullscreen enabled, my desktop often returns with 1/4 contrast, that is also a good indication that 10-bit color is working at least a bit. I made the hotkey combination Alt+Q for the "reload display driver" command, to solve the problem of a dark or black screen (with Aero disabled) after closing videos.

TheElix
13th November 2010, 14:06
Hey, Jan! I can't get your shader to work here. Could you write a short instruction for newbies like myself on how to enable your shaders in MPC-HC?

JanWillem32
14th November 2010, 19:57
To make a pixel shader work in MPC-HC:
Depending on your OS and synchronization needs, select "VMR-9", "EVR Custom Pres." or "EVR Sync" in the "View">"Options">"Playback">"Output" menu. You can hover the mouse pointer over the different renderer options to get a discription. Make sure that D3D fullscreen is disabled for the time being, you can activate it later on, when you've successfully enabled a shader.
Next, to enable a shader, right-click somewhere near the middle of a playing video, select "Shaders" and click on "invert" or some other shader that is really easy to test.
You might need to switch "Toggle Pixel Shaders" before a shader will work.
You can use multiple shaders in the "Combine Shaders..." or "Combine Screen Space Shaders..." menu. Not all shaders can be used in screen space mode.
Some shaders can't be used if your video card is old. View the comment about the pixel shader revisions in my shader to see wich video cards can use that shader.
Some shaders benefit greatly from enabling the the three "10-bit color" and "full floating point processing" options in "View">"Rendering Settings">"Presentation".

To add a new shader:
Tick "View">"Shader Editor".
Type in the name of a new shader in the long top left bar of the Shader Editor, to make the compiler write out a small, but useless script. Next, set the highest version pixel shader that your graphics card supports in the drop-down menu of the top right bar, avoid the software (sw) modes.
Remove all text from the main text box.
Copy the full text of a new shader and paste the text in the main text box.
If there's an error, the compiler will output an error code inside of the bottom message box. If all went well you will get a succes message, the calculation chain will be displayed and the number of instructions used will be at the end of the text.
You can alse use the drop-down menu trom the top left bar to select and edit an already existing shader.

Tip: because I like to switch between shaders, but don't want to disable D3D Fullscreen I made a basic text batch file (.bat) to enable a certain shader. An example for activating "invert":
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "Shaders List" /D "invert|" /F
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "ShaderListScreenSpace" /D "" /F

To disable all active shaders:
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "Shaders List" /D "" /F
REG ADD "HKCU\Software\Gabest\Media Player Classic\Settings" /V "ShaderListScreenSpace" /D "" /F

To activate multiple shaders, separate the names by "|" (pipe), but also keep the one on the end.

TheElix
15th November 2010, 11:51
Thanks for your thorough walkthrough. I think it deserves being duplicated in the first post.

I experience some problems though. I meet all prerequisites and do as you suggested: open shader editing, write-in a name for a shader, choose ps_3_0 (the program however changes it to ps_2_0 automatically) copy the text from your shader .txt file and paste it into the empty area. And press enter to process the shader. It gives me the message "D3DXCompileShader succeeded" and it gives me a 19-line code:
sampler s0 : register(s0);
float4 p0 : register(c0);
float4 p1 : register(c1);
#define width (p0[0])
#define height (p0[1])
#define counter (p0[2])
#define clock (p0[3])
#define one_over_width (p1[0])
#define one_over_height (p1[1])
#define PI acos(-1)
float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 c0 = tex2D(s0, tex);
return c0;
}
But I don't see any visible changes to the picture with the resulting shader...

Also, might I note that your shader pack which you posted some time ago here in .7z format cannot be extracted because you use unacceptable symbols in my OS (like ":"). Can you post the latest versions of your shaders again? Looking forward to seeing the effect of your shaders! :)

burfadel
15th November 2010, 12:42
yeah that happens to me too, just set it to PS 3.0, try readding the code, and then clicking back on the new name and pressing enter. That seemed to work for me. I had to recheck it again after closing and reloading, but seems fine now.

TheElix
15th November 2010, 14:24
I tried this. This hangs my MPC-HC for good. What build do you use?

burfadel
15th November 2010, 20:19
Usually the latest one I can find, but currently using 2727.

JanWillem32
16th November 2010, 05:41
@TheElix I did certainly not use ":" (U+003A, Unicode), but I did use "÷" (U+0247, Unicode). (the version that that has a dash in-between the dots to prevent the problems with any modern file system, both my Linux computer and Windows computers accept it)
The code you added is the standard code to delete, because it doesn't do anything. Just delete all lines, and add any code you want to insert.
MPC-HC can indeed be a bit nasty about inserting a new code, it only allows updating one of the three fields at a time.
Indeed, the main post should be more inviting for people that are interested in the works of pixel shaders, even newbies.
At the moment I'm trying to make a good set of final shaders, but "sharpen complex v3 + deband" is very hard to find good coefficients for. It fails completely on any resolution below 1080p input on the standard setting, outside the screen space renderer. However, I will try to make a final version soon.

Please do keep me informed if anything can be improved with my shaders. The most prominent examples are "sharpen complex v3 + deband" and the hybrid, they are at the edge of the insruction limit of PS 3.0, a lot can be wrong with it.

TheElix
16th November 2010, 10:18
Wow, I managed to get it to work thanks to your advice. But... uuuh... Look at this:
Sharpen complex v3 + Deband test 2
http://rghost.ru/3271929/thumb.png (http://rghost.ru/3271929.view)
No shaders
http://rghost.ru/3271936/thumb.png (http://rghost.ru/3271936.view)

So, uh, waiting for your final release :thanks:

JanWillem32
16th November 2010, 10:54
Test 3 edition has a better smooth gradient detection method but the sharpen values are too high for most pictures. As I said before: "The sharpening settings for test 3, sharpen complex v3 + deband are high, .375&.1875 or even lower towards .25&.125, are less over-sharpening for images with at least decent quality." Test 2 only had proper support for gradients covering a larger surface, and with less contrast.

TheElix
16th November 2010, 11:01
Like I said, I was unable to open Test 3 in your archive because WinRar gives me an error at the attempt of extracting. You might want to avoid using "÷" because apparently not all languages in Windows support it.

JanWillem32
16th November 2010, 11:48
I've looked up "÷", it is even part of the old ASCII extended character table (even non-Unicode filesystems can use those).
The reserved characters for both Unicode and non-Unicode filesystems in Windows are: < (less than), > (greater than), : (colon), " (double quote), / (forward slash), \ (backslash), | (vertical bar or pipe), ? (question mark) and * (asterisk).
Even very old filesystems support the ASCII extended character table for file names.
What happens if you unpack in a simple folder such as c:\temp\ , or in another folder with a very short file name structure?
It could also be Winrar, does it allow reading LZMA2 compressed file data? It's quite a new method to store data inside of 7-zip files.

TheElix
16th November 2010, 13:05
Heh, you were right. A newer version of WinRar did the job for me. I'm sorry.

JanWillem32
18th November 2010, 04:47
I've made some good progress on "test 5, sharpen complex v3 + deband". It rarely causes banding on gradients anymore, and the standard sharpen values are much more usable than those in the test 3 version. The other pixel shaders only needed a little bit of comment cleanup.
Only "sharpen chroma for SD&HD video input" could use a stronger version to accompany the current one. It's rather hard to decide how much stronger that version should be, as it depends a lot on the quality of up-sampling by the renderer, and the DXVA or software decoder. I do not think anyone would use this shader on actual 4:4:4 images, but 4:2:0 and 4:2:2 images can be up-sampled by many different methods.
This complete batch can be considered final, if no errors are found in the code.
The hybrid is not the most practical shader to implement. It's much easier to understand how to use the two separate shaders. The reason I made this shader, is to illustrate that he stacking method is wrong for heavy shaders. There isn't an option to use a complete frame in-between shaders, unless you use one shader as a non-screenspace shader, and one as a screenspace shader. That's why the hybrid is lighter on resources than the two separate shaders stacked (see the test in the opening post).

clsid
18th November 2010, 18:18
A bit off-topic, but wouldn't it also be a good idea to change how the shaders are stored?

I would suggest storing them as separate files instead of as strings in Registry/INI. That would have the following advantages:
- Makes it easier to add/remove shaders. Simply add or remove a file.
- Shaders can be modified with any text editor.
- The internal editor could be removed.
- No need to embed any default shaders in the executable.
- No bugs with storing large shaders in INI anymore.

Files could be placed in a subdir called "Shaders" or "PixelShaders" and files given the extension ".shader".

The minimum required PixelShader version could for example be placed on the first line of the shader file.

@JanWillem32
Are you also a C++ programmer? If so, would you be able to implement the above, and perhaps also the automatic shader version functionality that was previously discussed?

burfadel
18th November 2010, 20:27
I would also have added better portability between computers. If you copy MPC-HC to another computer, having it as the above suggestion would save setting them up on each application.

The internal shaders should still be that, stored in the programme, and only new or altered shaders needing to be placed using the method CLSID suggested. In the meny system, the additional shaders can show as a submenu to the current shader list.

JanWillem32
19th November 2010, 07:02
This sounds interesting. Let me add a few more things that might be improved:
- The ability to switch pixel shaders in the standard menu, not only the right-click menu.
- The ability to switch pixel shaders without having to start a video. (I use the D3D fullscreen mode.)
- Automatically setting the highest available pixel shader version for the resizer.
- Allowing a pixel shader to use the output from the resizer, but without the binding to the screen refresh rate like the screen space pixel shaders do. (My CRT can do 160 Hz for a smoother output, but no normal pixel shader can use that many frames per second.)

I've taken a look at the source code, but I could not find anything but the C++ and pixel shader codes for the resizers. I will definitely need someone to guide me though it, else I'll be searching for a very long time to find all the right items.

I focused from the beginning on the Y′CbCr-type shaders and "sharpen complex v3 + deband", because these needed the most work. The other default shaders could also lose quite a few instructions and have some comments inserted. Shall I work a on those too?
I am also looking for new, usable shaders and maybe some pixel shader resizers that can do a bit more than the bicubic resizer.

If the pixel shaders are to be loaded from a separate folder, I think it would be best if they are stored as .txt files, so that users can simply open them and read the comments in notepad.

CiNcH
19th November 2010, 19:51
I am also looking for new, usable shaders and maybe some pixel shader resizers that can do a bit more than the bicubic resizer.
Cool. Is changing the texture size possible without renderer interaction?

Are sharpen complex v3 and deband also available as standalone shaders?

PetitDragon
19th November 2010, 22:17
Yea, standalone versions of Sharpen Complex v3 and Deband will be very helpful.:)

JanWillem32
20th November 2010, 12:35
Changing the output texture size can only be handled by a pixel shader if it's embedded into the main program code, but that's not much of a problem.
"Sharpen complex v3 + deband" can be altered to change or disable functions. Disabling functions don't have much of an impact on the processing requirements, because the detection method that is used for both, requires the most processing.

I added a few comments to the test 6 version to make editing easier. I also changed the sharpen function to use smoothstep (Hermite spline function), instead of linear sharpen adaptation.

I cleaned up more comments to avoid confusion with the analog YUV&Y′PbPr and the digital Y′CbCr.

CiNcH
20th November 2010, 14:35
Just fur my understanding... Do the ATi PostProcessing algorithms that can be enabled within CCC work on the YUV image? Is color space conversion done afterwards and is it triggered by the renderer (as the connection format between the decoder and the renderer is a YUV format)? Custom MPC shaders work on the converted RGB image, right?

JanWillem32
20th November 2010, 15:10
MPC-HC shaders work on RGBA with a range of <0,1> (or rather <0,1], because of the conversion with integers) for both output and input. There is no access to any Y′CbCr data, that's why it's easy to fail at the conversion to Y′CbCr in a pixel shader. Pixel shaders that work on Y′CbCr data directly, do exist, by the way.
Driver-based decoders (DXVA), driver-based renderers, software-based decoders and software-based renderers can all access Y′CbCr and RGB data, depending on what stage they are processing in. It is even possible for some filters to work in the temporal space, to make frame-by frame comparisons.

CiNcH
20th November 2010, 15:25
Driver-based decoders (DXVA), driver-based renderers, software-based decoders and software-based renderers can all access Y′CbCr and RGB data, depending on what stage they are processing in.
I am just trying to understand which stage is introducing the chroma upsampling error with ATi. Standard renderers don't have this problem with ATi DXVA, so it seems to be the custom presenters that are at fault. On the other hand, nVIDIA DXVA does not suffer from this problem either when using the custom presenters.

JanWillem32
20th November 2010, 19:05
The ATi driver can deliver various formats to the renderer, if the renderer supports it. On my computer (with Catalyst 10.5a), there isn't a problem with chroma up-sampling when transferring video in a Y′CbCr 4:2:0 or 4:2:2 format to EVR CP, as the receiving renderer does the up-sampling. However, when RGB is transferred, the driver doesn't up-sample chroma as it should during the Y′CbCr to RGB conversion. On top of that, a lot of the processing/filtering options in CCC don't work if the output is RGB. There's no direct way for the renderer to "know" either that the input RGB data is faulty.
The advantage of the RGB mode is that it can do 10-bit integer per component, while all other formats are stuck with 8-bit integer (or less, when in a planar format like NV12). Not all of my videos are stored 8-bit, Y′CbCr, and 4:2:0 sub-sampled. Transferring them to the renderer as such would compromise quality.
To take it even further, the complete software chain can be opened to work with fp16 and fp32 (16-bit and 32-bit floating point) in DirectX 9 and 10 modes. DirectX 11 can finally handle fp64 too. DirectX 9 can output up to 10-bit integer RGB to the video card's output frame, DirectX 10 and 11 can use the output from the processing format without changing it. The video card then uses the color LUT to convert the colors of the output frame and (preferably) input that at the highest acceptable bit depth format for the digital connection, or pass it trough a DAC to output analog signals. Such processing chains are completely normal for full-screen DirectX games with HDR, but for a video player with that many dependencies on external hardware/software decoders and renderers, I can imagine it would be very hard to create such a chain. I do believe better quality modes can be achieved in some time, as the standards and capable processors are already available.

CiNcH
21st November 2010, 01:15
there isn't a problem with chroma up-sampling when transferring video in a Y′CbCr 4:2:0 or 4:2:2 format to EVR CP
So you are talking about the connection format between decoder and renderer (as the presenter component itself always works on RGB)? YV12 and YUY2 for example? The colorspace conversion is done by the mixer component, right? Guess that GPU colorspace conversion and the other Catalyst post processing algorithms only kick in when using NV12 colorspace (through DXVA2).

However, when RGB is transferred, the driver doesn't up-sample chroma as it should during the Y′CbCr to RGB conversion.
So this is the case when using DXVA and NV12 colorspace, right? But both, EVR Standard and EVR Custom, trigger DXVA with NV12 colorspace. Only EVR Custom suffers from the bad chroma upsampling however.

de66ka
21st November 2010, 09:30
Hello JanWillem32,

I'm using your "brightness, contrast,....control" script adjusting the output of my renderer. What I'm missing is a feature to adjust the "gamma".
Is there the possibility to implement such a control in this script?

Thanks in advance
de66ka

JanWillem32
21st November 2010, 13:37
@CiNcH I only have bad chroma up-sampling when I force 10-bit RGB input. The "Display Stats" screen then also shows RGB32 input. (The internal format is R10G10B10X2.) The ATi driver doesn't mind converting the processing format to 10-bit RGB, but fails at up-sampling while doing so. Do you have an example of instances when up-sampling fails with other input formats?

@de66ka That was easy. It is however a RGB color control function, unlike the other functions that work on Y′CbCr components.

CiNcH
21st November 2010, 13:58
I am not using 10-bit at all.

I did the following tests now:

Source: recording on ATV with red logo on black background (MPEG-2 576i) (chroma_test.ts (http://members.inode.at/762450/chroma_test.ts))

Filter chain: ffdshow -> EVR Custom (MPC-HC)

ffdshow YUY2 output: chroma not interpolated
ffdshow NV12 output: chroma not interpolated
ffdshow RGB32 output: chroma is properly upsampled within ffdshow

I verified this with the CyberLink decoder.

Filter chain: CyberLink Video/SP Decoder (PDVD10) -> EVR Custom (MPC-HC)

CyberLink DXVA NV12: chroma not interpolated
CyberLink SW YUY2: chroma not interpolated


I tried the same thing with Standard EVR.

Filter chain: ffdshow -> EVR

ffdshow YUY2 output: chroma is properly upsampled
ffdshow NV12 output: chroma is properly upsampled

JanWillem32
21st November 2010, 15:35
That is really odd. I can't reproduce the problem at all. DXVA testing for SD content is not possible with Catalyst 10.5a. All software decoders, including the internal one, are rendered okay. I only had to disable 10-bit RGB input mode for testing, because it is incompatible with the current software decoders.
What driver version are you using? I haven't used any other versions after 10.5a, because they fail at DXVA decoding with 10-bit RGB output. Maybe newer drivers have a few other glitches, as well.

CiNcH
21st November 2010, 15:43
This (http://forum.doom9.org/showthread.php?p=1456318#post1456318) is what it looks like when chroma upsampling fails.

I am using Catalyst 10.11 with a Radeon HD 3650. I always had this problem with the MPC-HC Custom Presenter.

JanWillem32
21st November 2010, 16:20
A HD 3650 is one of the UVD+ chips. That is a bit hard to compare to my card that supports UVD 2. There is a difference in the amount of work that the video decoder, mixer and renderer offload to the GPU. Now I'm wondering too if the hardware, driver or software is to blame in your case. In my case it is clear that the driver skips the up-sampling step when converting colorspaces. In your case, the output from the video decoder is in a planar format, but the mixer/renderer skips up-sampling. That has never happened to me.
Well, at least your GPU can easily handle the up-sampling scripts.

CiNcH
21st November 2010, 16:34
Question is how standard EVR handles it properly..

JanWillem32
21st November 2010, 19:01
On top of that, how differently does MPC-HC treat the three EVR types? I always thought that the only difference was the subtitle overlay and the different synchronization clock, but for example, the "Display Stats" screens are different too.

I've made some progress on editing the standard shaders that were not in my releases. I only found one problem. The denoise shader is double defect. It works by sampling 128 pixels in an eight-pointed star-shape, instead of a normal circle. It does nothing more than adding up the values, so it only blurs and brightens. It does not compare any color, brightness or anything that would make it a real denoise shader. Does anyone know some shaders that can do a real denoise? Preferably one that has the same quality as the versions in the nVidia and ATi control panel.

de66ka
22nd November 2010, 06:55
@JanWillem32
Thank you for implementing the Gamma-Switches in your script. Works like a charme. So I'm able to correct the output without changing the driver settings. For my taste most of the HD-Videos are way too dark.

Thank you, de66ka

JanWillem32
23rd November 2010, 13:11
I agree that many Blu-ray movies are mastered quite a bit darker then what I've seen in theaters. A few seem a bit brighter as well (Alice In Wonderland and some anime productions for example).
Outside of the ugly teal-and-orange, loudness war and dirty tape problems, that are present in the studio master, Blu-ray mastering seems to be difficult, too. Setting the normal gamma from 2.6 in the studio master for Digital Cinema to the two gamma functions in BT.709-5 for Blu-ray doesn't always turn out that well.
Many consumer-grade LCD panels have very bad dark-to-black accuracy, that's a common problem. I've even seen that a TV totally crushes dark scenes to black by dimming the back lights. My old CRT may not be the brightest anymore (at 89.8 cd/m² maximum) and the D-sub analog connection is leaky (I can easily see left-to-right bleeding artifacts), but it still outperforms my very expensive projector whens it comes to displaying a very dark scene (not having a back light has its advantages). The general image that my projector makes is less "hard", it's easier to watch for a longer period, unless it projects a very, very bright picture hat makes my eyes hurt because of the total amount of light.
Considering the great difference in consumer-grade viewing systems/screens, it's hard to choose the perfect color layout for a Blu-ray. I just hope that people mastering Blu-rays will choose to feed the raw Digital Cinema master (with the standard mathematical conversion to BT.709-5) with a lot higher and more consistent quality then they have done before.

I need more inspiration to make "denoise", but all other shaders are finished. Maybe I will make an intermediate version "sharpen complex v2 + deband" on PS 2.0a minimum to fill the gap between v1 and v3.

Phaser
25th November 2010, 12:04
JanWillem32, is it possible to make a separate Deband shader v3 (without sharpen complex)?

JanWillem32
25th November 2010, 12:44
I'm looking if I can make the version of "test 4, sharpen complex v3 + deband" that will only compile on DirectX 10/11, more DirectX 9 friendly, as that one can also do denoise, but the instruction limit is a big problem (it's actually faster, even with more instructions). I made new versions of almost all shaders to make use of some speed-up tricks, but I really want to make "sharpen complex v2 + deband", a revision of "sharpen complex v3 + deband" and at least something that can denoise for a next release.
At the moment "sharpen complex v3 + deband" can become deband-only if you define "SharpenFull" and "SharpenPartial" 0.

toniash
25th November 2010, 13:23
@JanWillem32

What values do you would recoomend for SD?
Thanks for your work

PetitDragon
25th November 2010, 14:42
but I really want to make "sharpen complex v2 + deband", a revision of "sharpen complex v3 + deband"

can't wait to see that!:)

CiNcH
25th November 2010, 16:48
I'm looking if I can make the version of "test 4, sharpen complex v3 + deband" that will only compile on DirectX 10/11, more DirectX 9 friendly,...
ps_3_0 is DirectX 9c, isn't it?

G_M_C
25th November 2010, 19:04
I'm following this thread with great interest. I've tested hybrid v3 with 720p/1080p film, and it works fine on my HD5770. The GPU gets worm, shure, but it easily keeps up with framerate. I found the hybrid/debanding shader very usefull on encodes of live-concert performances (like Muse's Seaside rendezvous) where the shader seemed to help reduce banding often seen looking at lightbeams created by the spotlights.

If you make another hybrid, say v4, is it not also a good idea to make the hybrid-components available seperately ?

(Super werk Jan Willem, erg bruikbaar !)

JanWillem32
26th November 2010, 01:08
@toniash For which of the 31 scripts do you need values? I did a lot of guessing work for on most shaders to get them at least functional.
@PetitDragon v1 and v2 will be made by weakening the v3 version, so I'm going to finish that one first. I'm planning to bind v3 to the limits of PS 3.0, v2 to the limits of PS 2.0a and v1 to the limits of PS 2.0.
@CiNcH That's right. http://en.wikipedia.org/wiki/Pixel_shader
@G_M_C Spotlights can illuminate a lot of dust in the air. Many automatic sharpening filters in cameras and after-effect filters will over-sharpen because of that. It's good to know that debanding can work to soften things up. My newer shaders can also be modified to compensate for noise, that may help as well. A HD5770 can easily execute hybrid test 6 or 7 on its idle clocks, maybe it will even heat up a bit less with those. Hybrid versions are just for solving a performance problem, by the way. Once the "combine shaders" method is improved to the point that it doesn't take a huge performance hit anymore, the hybrids are useless (see my test in the opening post). (Verder, ik heb het graag gedaan, hoewel dit beduidend meer tijd heeft gekost dan ik geanticipeerd had.)

The "test 7, sharpen complex v3 + deband + denoise" shader was made by altering the DirectX 10/11 version, it is a lot different from the test 6 version (also included). Adjusting values was a real disaster, and it still needs some work to get decent parameters for the outer radial layers. It can at least do a decent job on dithering, grainy and mosquito noise. Sharpening detection is somewhat limited (a circle radius of 2.5 pixels), but it performs quite well. On top of that it is a lot lighter in general, unless it denoises and debands a completely blurry or plain frame.
Other shaders have not been improved a lot, there's only a minor speedup for some. I lowered the default sharpening values for most of the sharpening shaders. That's because the original shaders horribly over-sharpen and I don't want to adjust the output of my versions to match that anymore. Altering the sharpening values to your preferences should be easy enough if you read the comments.

CiNcH
26th November 2010, 13:10
Are shaders > ps_3_0 even compiled? I thought that the custom presenter within MPC was DirectX9.

JanWillem32
29th November 2010, 20:06
I use a separate program that can use a decent font size, automation, optimize functions and syntax highlighting for writing scripts. For testing purposes, I often compile something for DirectX 10. If I like what I see, I can then try to simplify the code to suit the limits of the lower pixel shader versions.
The pixel shaders in MPC-HC are all DirectX9, with either a PS 2.0, 2.0a or 3.0 profile.

I made a test 8 release. Only the sharpening shaders have been changed from the test 7 versions. I'm very happy with the performance of "test 8, sharpen complex v3 + deband + denoise". Although the sharpening is a bit mild, it does apply a very good "clean-up" effect, even when zooming in on an image. On top of that, it performs well on very high contrasts, so even with higher sharpening values, it doesn't tend to over-sharpen.
I'm looking forward to make a final release soon, that includes v1 and v2 versions of "sharpen complex v3 + deband + denoise" and updated functions for the regular "edge sharpen" and "sharpen" functions.
To reply to my own opening post; I believe all of my shaders, except for the hybrid, are good enough to replace the complete set of shaders included currently in MPC-HC. I'm looking forward to make a request soon to include them in a future MPC-HC build. If any other other program can use my shaders, whether it's for video, still images or 3-D rendering, I will be happy to submit my shaders for those programs too. Please inform me which programs could make good use of them.

burfadel
30th November 2010, 03:54
In the hybrid script, you repeated this line in the comments at the top:

// For video processing, an above average GPU is required, often even on full GPU and memory clock speeds, this is written in 2010.

It seems to work well though!

JanWillem32
30th November 2010, 04:43
You are right, so I cleaned up a few comment lines.

TheElix
30th November 2010, 18:28
Shaders Disabled
http://rghost.ru/3435311/thumb.png (http://rghost.ru/3435311.view)

Hybrid test 8 enabled
http://rghost.ru/3435325/thumb.png (http://rghost.ru/3435325.view)

Ugh... In photography it's called excessive digital noise reduction. Not a good thing.

JanWillem32
30th November 2010, 18:53
I wish that I could provide with automatic noise adaptation. Unfortunately, that will be quite hard. I can however see if the sharpening to contrast level adaptation can be improved, without damaging the dynamic range.
This scene can still be properly modified if you lower the "NoiseLevel" factor.

The default:
// NoiseLevel; <.5,4>, detection noise factor, .5 is for very plain, lossless, synthetic images, 1 is normal for digital lossy video and images, higher values will help counter grainy noise on surfaces and gradients, at the cost of the detail level
#define NoiseLevel 1

TheElix
30th November 2010, 19:32
I understand that at brighter scenes and in other source videos your shader will work differently. However, if we take sharpen complex v.2 for example it will show consistency at various conditions. Anyhow, keep up the good work!

JanWillem32
30th November 2010, 23:18
The original sharpen complex 2 is not consistent either. When it processes images, it compares the calculated edge detection value to the edge sharpening limit. That edge detection value can never reach the edge sharpening limit on low brightness images, because it doesn't correct for the brightness.
To solve that in the test 9 version of my shader, I added a bit of brightness detection (full detection is much too taxing on registers). It does cost a bit of debanding quality and it is just under the maximum complexity limit for PS 3.0, so I can't really add more functions. I do like how it handles a certain scene with a night sky. The brightness and contrast adaptation is more balanced when compared with the test 8 version.

Edit:
I managed to make a small improvement in the distribution of the sampling area, brightness calculation and debanding quality for the test 10 version.

TheElix
2nd December 2010, 22:53
Sorry for the delay. Just downloaded and tested your v10 Hybrid shader. Here we go:

Shaders Disabled
http://rghost.ru/3462453/thumb.png (http://rghost.ru/3462453.view)

Hybrid v10 Shader
http://rghost.ru/3462463/thumb.png (http://rghost.ru/3462463.view)

Sharpen Complex v2 Shader
http://rghost.ru/3462491/thumb.png (http://rghost.ru/3462491.view)

Well... Much better than v8! It sharpens the image in quite a different way than Sharpen Complex v2. Although the digital noise grain becomes more distinctive too. Let's look at another picture:

Shaders Disabled
http://rghost.ru/3462510/thumb.png (http://rghost.ru/3462510.view)

Hybrid v10 Shader
http://rghost.ru/3462512/thumb.png (http://rghost.ru/3462512.view)

Here I can't say the shader is benefical to the picture. Especially in the dark areas of space. But maybe I got the wrong idea as to what this shader does.

nurbs
2nd December 2010, 22:58
What's the problem with the second set of pictures? I'm looking at them on a CRT here and the dark areas of space look fine.

TheElix
3rd December 2010, 00:36
The transients between far-standing colors are more sharp thus more evident.

JanWillem32
3rd December 2010, 11:04
The first example has a lot of noise, of different types. It will be hard to remove most of it, while keeping the details. I think that it could use a "NoiseLevel" setting of 1.5 or 1.75 to clean things up a bit.
The second example is synthetic. I use a "NoiseLevel" setting of .75 on those because the shader doesn't need to clean up anything else but quantization and lossy compression noise. If you think it over-sharpens too, you can lower the sharpening amounts.

CiNcH
3rd December 2010, 18:14
YUV <16,235> to any RGB conversion is a bit lossy, so if the RGB range is only <16,235>, floating points get truncated more than with a range of <0,255>.
What is the better trade-off? The loss of precision due to truncation or the banding that is introduced when expanding levels?

JanWillem32
4th December 2010, 01:36
First of all, all shaders in MPC-HC output "R32G32B32A32_FLOAT" (128 bits in total), even if the "Full Floating Point Processing" option is turned off. I advise to use that option, as it allows less degradation from the different rendering stages, even if input and output are limited to 8- or 10-bit integer formats.
The video file to display path in Windows requires Y′CbCr data to be converted to RGB, even if data is converted to Y′CbCr for DisplayPort, HDMI or dual link HD-SDI transport. This website specifies that all DirectX color formats are full range RGB:
http://msdn.microsoft.com/en-us/library/ff471325%28VS.85%29.aspx
For BT.601 [SD] and BT.709 [HD], the obligated Y′CbCr conversion to Wide Gamut RGB color space or sRGB color space changes the gamma functions, chromaticities of the primary colors and the white point. This means Windows, DirectX, drivers and the video card will process these in a wrong way if the input from the video renderer is limited range RGB.
That's why I've been busy making shaders that can correct these functions. I do want to remind everyone that conversion to Y′CbCr with <16,235> or <64,940> luma ranges, is really a thing for the video card and drivers to handle. The best I can do, is provide shaders that can compensate functions for the <16,235> and <64,940> luma ranges inside of full range RGB. However, it is far from correct and all further changes to the picture after those shaders will further lower the color quality. (I added warnings in the comments of the new shaders.)

Once I'm finished with those shaders, I will post them, but it's really a lot of work to make and comment them.

I know that I didn't quite answer your question, but I think I made it clear that using a limited range RGB format is problematic, as it doesn't relate very well to the limited range Y′CbCr formats.

Edit:
I decided to reduce the amount of code, to reduce the size of the shaders (without compromising any quality), and I corrected some small errors.
To illustrate the RGB gamma differences between the common formats, I included basic gamma transformation shaders. (To complete them, the CIE-type color transformation matrix for both input and output has to be added as well, but that's more something for someone who's programming a video renderer or mixer.) These are not for regular use, so I marked the file names with a "~". I also included a text file with the standard Y'CbCr and RGB conversion codes for developers. The "detect even or odd coordinates" shader was used to verify some code of the chroma up-sampling shaders, it might also be useful for other developers.

Edit:
I resolved a few mistakes in a few shaders. I added basic sharpen complex "v2", "v1" versions and "v3" with 5 different noise level presets (in alphabetical order).

Edit:
Because I wanted to speed up some instructions on some shaders, I tried to use partial precision mode on a few. However, I never saw any performance improvement. I now know why.
I read this article, and tried the "PSPrecision" application:
http://ixbtlabs.com/articles2/ps-precision/

The application stated:
Device: ATI Radeon HD 4800 Series
Driver: aticfx32.dll
Driver version: 8.17.10.24

Registers precision:
Rxx = s23e8 (temporary registers)
Cxx = s23e8 (constant registers)
Txx = s23e8 (texture coordinates)

Registers precision in partial precision mode:
Rxx = s23e8 (temporary registers)
Cxx = s23e8 (constant registers)
Txx = s23e8 (texture coordinates)

32-bit precision for floating-point numbers is not bad at all (unless you need doubles or larger for iterative functions or scientific calculations), but it seems partial precision mode for pixel shaders is simply ignored by my video card. As the examples state in the article, it could have been a lot worse. The only thing that makes shaders run faster on my hardware is by compiling them with the highest available PS version.

CiNcH
6th December 2010, 23:00
For BT.601 [SD] and BT.709 [HD], the obligated Y′CbCr conversion to Wide Gamut RGB color space or sRGB color space changes the gamma functions, chromaticities of the primary colors and the white point. This means Windows, DirectX, drivers and the video card will process these in a wrong way if the input from the video renderer is limited range RGB.
So this means that the ATi CCC color pixel format 'RGB 4:4:4 Studio' is basically useless as some component within the video display chain (DirectX, Windows Color Management) will always distort the result in some way due to full range assumption?

How about good old Overlay? It bypasses all these "layers", doesn't it? Too bad it expands levels by itself.

JanWillem32
7th December 2010, 01:37
There are two ways of compressing the ranges, the cheap way is by lowering the RGB contrast to a direct range of <16,235> or <64,940>. That will work on displays that simply stretch RGB linearly up again to <0,255>, <0,1023> or more, depending on the display's processor calculation bit depth, followed by the step of direct output to the display (it's only impractical to first compress and then expand again if it's not necessary). However, many devices expect perfect Y′CbCr with BT.601, BT.709, or BT.1361 characteristics, even when RGB is received (but the first Y′CbCr to RGB conversion step is omitted). That will distort the color matrix and gamma. A common example: the basic red is much purer for Wide Gamut RGB, sRGB, BT.709 and BT.1361 than for BT.601. If a TV expects BT.601 but receives red from a Wide Gamut RGB color space or sRGB color space, it will crush it to the maximum, even if the format is limited range RGB.
I designed my shaders to work by conversion to Y′CbCr, compress the ranges from <0,1>, <-.5,.5> and <-.5,.5> to <1/8,235/256>, <-15/32,15/32> and <-15/32,15/32> (as the Y′CbCr standards dictate for signed floating points) and then output RGB again, without gamma or color matrix correction, as those functions only distorted the picture even more when I tested Y′CbCr limited range on my projector against full range RGB (display color profile disabled for this test).

I do not know what functions the drivers use to convert the input RGB data. I do know it requires full range RGB input to function in the first place.
Any video card has to receive a full range, full resolution RGB texture/frame before it will output, because there are no other formats it will take, even if the driver converts it to another format for the output port connection. The overlay renderer still has a color mixer inside, otherwise it couldn't output any decent information to the system.

There's no way you can use a pure Y′CbCr path on a PC, other hardware units will often convert Y′CbCr to RGB and vice versa too, to apply some filters. Banding is quite a big problem because the input formats are often not that great, and many processing formats are limiting as well. Neither my old CRT as my new (and expensive) projector can do any debanding. Things started to improve when I used a calibration device on both, and used some software filtering to improve the picture. I replaced my stand-alone blu-ray player because it couldn't come close to my PC in neither audio or video processing.

By the way, those who use display calibration correctly, don't have to worry too much about Wide Gamut RGB, sRGB, BT.601, BT.709, BT.1361 color spaces and gamma functions, as these are all converted to the display's own capabilities by RGB to RGB transfer functions. If banding is in the source, the best thing you can do is to keep the digital pipeline from source file to display panel as wide as possible, and maybe filter a bit in-between.

Deshi
8th December 2010, 11:50
Hi everyone,

I've trouble testing your PS.
When I compile them in MPC-HC I can't get over 125 lines of codes, meaning that most of your PS won't work.

My VGA supports PS 4, but in MPC-HC I can only choose PS 3 ou PS 3sw max.

Is that the problem or do I missed something somewhere in the process of creating the PS from the start ?

Thanks for the help.

PetitDragon
8th December 2010, 13:45
Hi everyone,

I've trouble testing your PS.
When I compile them in MPC-HC I can't get over 125 lines of codes........

Uncheck "store settings to .ini file" in your mpc-hc options sheet.

JanWillem32
8th December 2010, 13:56
That is a very common problem if you save settings to a .INI file. I know it's nice to have portability for your settings, but it can't save big shaders (yet). I personally stopped using the saving to .INI setting.
If you want to make a copy of your settings from the registry:
- run regedit
- expand the tree to "HKEY_CURRENT_USER\Software\Gabest\Media Player Classic"
- right-click the "Media Player Classic" key
- click the export option
It produces an executable .REG file that you can use as a back-up or to transfer settings to another PC. I use several smaller .REG files to switch between shader presets, too.

Maybe I should add a warning inside my shaders to avoid using a "sw" (software) mode, as it often doesn't work at all. Shader code is heavy to run on even a reasonably new CPU, as it's meant to run in parallel on many pixels at once. GPUs don't mind working on over a million parallel threads, but CPUs have much fewer cores to compute those.

Deshi
8th December 2010, 15:02
Thank you all !
:cool:

CiNcH
8th December 2010, 19:18
I have done some further testing concerning the chroma upsampling problem that I am experiencing with the MPC-HC custom presenter and found out the following...

Chroma seems to be interpolated when the display is 1080p50. When resolution is 720p50 (native resolution of my Sanyo PLV-Z4) or 1680x1050 (TFT) chroma is upsampled by doubling the values. (GPU is always the same HD 3650)

So maybe it is resolution dependant and not specific to < HD 4000 series. Still one has to keep in mind that this is not happening with standard EVR, but only with the custom presenters.

JanWillem32
8th December 2010, 20:28
Can you provide a screenshot of both resolution states with an exact magnification of 400%? (Like I did with my four pictures at the start of this topic.)
You can achieve exactly 400% by using "View", "Video Frame", "Double Size" and then "View", "Pan&Scan", "Increase Size" (a lot of times). I assigned a few F# keys of my keyboard to these functions using the "View", "Options", "Player - Keys" menu. I assigned a lot of these kinds of functions to keys, because I've been busy making screen space resizer shaders. Those require the "View", "Video Frame", "Normal Size" setting for input, by the way.
I already made "Catmull-Rom Spline resizer", "4÷2÷0 Catmull-Rom Spline chroma up-sampling for SD&HD video input" and "Lanczos2 resizer". I'm currently investigating the "ringing beasts": multi-tap Spline and Lanczos.

CiNcH
8th December 2010, 21:24
Can you provide a screenshot of both resolution states with an exact magnification of 400%?
Hm, they look pretty much the same then. What could be the cause of the bad chroma at lower screen resolutions (e.g. 720p)? Source is 576i.

JanWillem32
8th December 2010, 22:18
If the exact magnification screenshots of both resolution states show bad chroma upsampling, then the display resolution is not a factor in the origin of this problem. It just means that the regular resolution scaler is blurring everything if it stretches a picture up a lot, including the bad chroma edges.

Edit:
For those who are interested, here are my resolution shaders. These include chroma up-sampling shaders that work normally if you set them as the very first pixel shader.
The Spline-type resizers are all right, but Lanczos2 is a bit more blurry than I expected it to be. All of these shaders will need additional comments, but I will add those when I'm confident that the shaders work properly. It's too bad that the 2-tap Spline uses just a few too many registers to compile in DirectX 9. In my DirectX 10 "teapot" renderer it does a proper upscale of textures. The same effect can be achieved by upscaling 2× with the "×2" shader, and then upscale further with a second shader in the stack.
Downscaling should work if the shader is in the regular shader stack.
Upscaling should work if the shader is in the screen space shader stack.
Scaling shaders require the "View", "Video Frame", "Normal Size" setting (blending multiple scalers is generally a bad idea).
Because the video input resolution isn't passed on to the shader, you will have to set your video input resolution for the shader, or set the magnification factor.

CiNcH
9th December 2010, 06:42
If the exact magnification screenshots of both resolution states show bad chroma upsampling, then the display resolution is not a factor in the origin of this problem. It just means that the regular resolution scaler is blurring everything if it stretches a picture up a lot, including the bad chroma edges.
Then I don't get why it looks a lot better when being upscaled to 1080p compared to 720p or 1680x1050.

Upscaling should work if the shader is in the screen space shader stack.
What is your upscaling shader worth when the image has already been upscaled by the renderer?

JanWillem32
9th December 2010, 07:58
Total resolution up-scaling by normal means will always blur, alias and/or make interpolation halos over the source image, that can be so much that the bad chroma up-scaling becomes much less apparent. It is still present, however. If you use exact magnifications (preferably with nearest neighbor scaling), there's no way you can overlook bad chroma up-sampling. To make it even more visible, you can view the chroma data directly with my "chroma" shader.

Scaling shaders require the "View", "Video Frame", "Normal Size" setting. This disables resolution scaling by the renderer, the picture is then centered on the screen with either black borders or parts of the frame cut off.

CiNcH
9th December 2010, 11:39
Scaling shaders require the "View", "Video Frame", "Normal Size" setting. This disables resolution scaling by the renderer, the picture is then centered on the screen with either black borders or parts of the frame cut off.
Ah, I see, I will conduct a comparison tomorrow.

Can you provide a screenshot of both resolution states with an exact magnification of 400%? (Like I did with my four pictures at the start of this topic.)
You can achieve exactly 400% by using "View", "Video Frame", "Double Size" and then "View", "Pan&Scan", "Increase Size" (a lot of times).
There seems to be a problem.

What I am doing:
- I stretch the video frame to double size
- I increase the size via 'Pan&Scan' until the status bar reads 2.00

I think I am at 400% now, right?

I then try to navigate to the top right corner (with CTRL+4/8/6/2), where the ATV logo is (see my posted sample). On my 1080p screen I can go there. But on my 1680x1050 screen, the logo does not seem to be part of the rendered image any longer. I have to decrease size again until I am at about 1.88 to see at least the 'A' within the logo.

JanWillem32
9th December 2010, 12:06
The repositioning filter uses the internal re-sizer, and that one indeed doesn't compensate for resolution/scale/magnification changes. The screenshots I took were from the center of the image. You can try to use the "chroma for SD&HD video input" shader on a high chroma contrast image to directly view the chroma data. That will definitely pinpoint the chroma up-sampling problem, if present.

CiNcH
9th December 2010, 13:09
I will try it at 1080p. Is the ATV logo good enough? Shall I use magnification?

JanWillem32
9th December 2010, 14:04
400% nearest neighbor scaling doesn't distort the picture much. It does have a bug that creates a central horizontal and vertical line line when scaling (even by exact amounts), so avoid these when taking a crop of a screenshot.
If you can, don't re-position from the center of the image. Try to make comparison screenshots with and without the chroma up-sampling shader, like I did with my first set of pictures. You can use about every input picture if you use the "chroma for SD&HD video input" shader, as it can expose chroma blocks on any color border.

I made a nice chain of of shaders, and to allow people to compare the quality, I made three screenshots of a 400% scaled medium bitrate AVC encoded HD video.
standard; see page 1 of this thread for most of my settings, MPC-HC v1.4.2752.0, no shaders activated (bad chroma up-sampling is also visible).
flitered; pixel shaders: "4÷2÷0 Catmull-Rom Spline chroma up-sampling for SD&HD video input", "gamma conversion of BT.709 or BT.601 derived full range RGB to linear RGB", "test 12, sharpen complex v3 + deband + mild denoise" (noise detection factor .75, square root removed from the equation for sharpening) or "test 12, sharpen complex v3 + deband + minimal denoise" (noise detection factor .625, square root removed from the equation for sharpening)
screen space pixel shaders: "Catmull-Rom Spline ×2 resizer", "Catmull-Rom Spline ×2 resizer" (to get 400% magnification), "gamma conversion of linear RGB to BT.709 or BT.601 derived full range RGB"
The screenshots are 2048×1440 8-bit raw PNG format files from direct "Print Screen" screenhots saved in GIMP, 2.7 MB each.

CiNcH
9th December 2010, 17:06
This is what it looks like on the 1080p screen:
http://members.inode.at/762450/chroma_diff.png

Guess I am always suffering from bad chroma upsampling. Though for some reason, it is less apparent on the 1080p screen.
I first thought it may be due to the 16:10 TFT and a faulty/bad upscaling in this case. But it is also as apparent on the 720p projector (without any magnification or filtering, just 576i deinterlaced and upscaled to screen space).

CiNcH
9th December 2010, 17:54
Compared to the madVR Lanczos implementation yours is extremely blurry. Even a lot worse than Bilinear.

Small comparison between your Lanczos and MPC-HC Bicubic

Source: TWILIGHT DVD VTS_01_2.vob Frame 5882 (720x576)

Bicubic -0.60 (http://members.inode.at/762450/bicubic.png)
Lanczos2 (http://members.inode.at/762450/lanczos2.png)

JanWillem32
9th December 2010, 20:21
I already thought that the display resolution couldn't be a key factor in the lack of chroma up-scaling. It should be one of the transformations before the color format converts to RGB, while the display resolution is only passed to the renderer in the texture to screen space stage (an RGB mode).
I know that "my" Lanczos2 looks blurry. I only borrowed the code and made it a bit more organized. I didn't check the methods, however…
I did build the Catmull-Rom Spline types almost from scratch, and those are fine compared to some other single-pass resizers. It also helped a lot that the first shader I made of that type worked right away, as that doesn't happen very often to me.

bobdynlan
9th December 2010, 22:55
Hallo JanWillem32! One of my first attempt at shaders was a film-grain one, made "blind" but surprisingly it did work. You seem like you have the skills and the tools to do a proper one. I will not put up a request but instead a challenge :) because I still believe it's one of the most needed shader extension for MPC-HC.

I don't know about others, but when I watch a movie I like that extra feeling. It's one way closer to dreams (all dreams have some HDR applied to them). I don't need pixel perfect "reality", 5'o'clock TV News in my country beats the hell out of Paranormal Activity, Cloverfield and their likes. Just to chase away those "purists"...

This film grain thing can actually improve perceived details from the distance, and hide some of those damn color bands. Are you up to the challenge? :rolleyes:

I don't know much about directx and gpu processing, but did some basic translations/adaptations from various sources. Here it's a noise(grain) shader, good against color bands, giving some film effect, any improvement is welcomed: //ps_2_0
/* I've missed Xvid's film effect
bobdynlan's adaptation of GrainPS2 from Looki's Shader Pack V 2.0 */

sampler s0 : register(s0);
float4 p0 : register(c0);
#define clock (p0[3]) /* it was static only before I found this :D */
#define PI acos(-1)

float mccool_rand(float2 ij) {
/* Random algorithm by Sylvain Lefebvre */
const float4 a=float4(pow(PI,4),exp(5),pow(13, PI / 2.0),sqrt(1997.0));
float4 result =float4(ij,ij);
for(int i = 0; i < 3; i++) {
result.x = frac(dot(result, a));
result.y = frac(dot(result, a));
result.z = frac(dot(result, a));
result.w = frac(dot(result, a));
}
return (float)result.xy;
}


float4 main(float2 tex : TEXCOORD0) : COLOR
{
float fStrength = 0.10; /* 0.05=min; 0.1=LOW; 0.15=med; 0.2=strong */

float clkvar = 0.001; /* 0.0=static grain 0.001=fix some noise banding */
float4 c1 = tex2D(s0,tex);
float rand = mccool_rand(tex+clkvar*clock)*fStrength;
// c1.rgb=(0.5,0.5,0.5); /* display only grain */
c1.rgb *= float3(1-rand,1-rand,1-rand);

return c1*(1+fStrength/2);
}

JanWillem32
10th December 2010, 09:43
I already have a bunch of film and special effect shaders in storage. Those are mostly game-adapted, unfinished or distortion effect shaders. I currently have: sepia (brownish grayscale, a bit red-sensitive), film roll drive scratches (vertical scratching on film), dust (doesn't quite look realistic yet) and a few types of noise (digital static, grain, fog, smoke, rain, snow and two types of dithering).
Your shader does look interesting, but the notion of "fix some noise banding" is wrong. Banding in the digital realm is due to limited bit depth of source files and displays. The correct way to handle banding from a source is to use a type of deband filter. For output it will need temporal dithering with settings for 5-bit to 11-bit digital displays or connections. The input type of shader I made already works quite well. The output type of shader I made is difficult to analyze, as it needs to be run on the output frame texture, that's after the color correction. The temporal dithering methods don't use random noise. They are fixed dithering functions, using fixed color bit depth with sampled pixel color, coordinates and time.
For digital static grayscale noise (that's what your shader does, it's not exactly film grain), it will require conversion to linear RGB or RGB with a constant gamma (this can already be done with my experimental gamma shaders). Running this shader directly on video output will change the darkest colors differently than the lighter colors.

I will see what I can do, but I'm not the best nor the fastest programmer. I'm planning to first finish my current set of shaders, as most of them just need some comment editing. Later on, I will review the film and special effect shaders (including yours). To illustrate my programming speed: earlier in this thread, burfadel mentioned adding noise and I came up with temporal dithering. Since then, that item has been on my wish list, but the experimental shader just doesn't work exactly right yet.
My first "denoise" shader was made in September and my first "chroma up-sampling" shader was made in October. My "Hello world!" shader was made over 2 years ago.
To add variables: -My disease complicates things from time to time, so I can't always do everything I want immediately. -My programming skill certainly isn't great, so I sometimes really need help from other programmers, but it's hard to get decent programmers to do something without payment. I'm not going to pay anyone, so I'm left with the very scarce free help I can find.

For now, I will store a quickly cleaned up version of your shader, as it's a bit different from those that I already have.

By the way, the introduction of HDR (high dynamic range) rendering changed a lot of vertex, geometry and pixel shaders. As far as I know, direct noise isn't one of them. What HDR implementation did you mean?

CiNcH
10th December 2010, 10:03
Your shader does look interesting, but the notion of "fix some noise banding" is wrong. Banding in the digital realm is due to limited bit depth of source files and displays. The correct way to handle banding from a source is to use a type of deband filter. For output it will need temporal dithering with settings for 5-bit to 11-bit digital displays or connections. The input type of shader I made already works quite well. The output type of shader I made is difficult to analyze, as it needs to be run on the output frame texture, that's after the color correction. The temporal dithering methods don't use random noise. They are fixed dithering functions, using fixed color bit depth with sampled pixel color, coordinates and time.
For digital static grayscale noise (that's what your shader does, it's not exactly film grain), it will require conversion to linear RGB or RGB with a constant gamma (this can already be done with my experimental gamma shaders). Running this shader directly on video output will change the darkest colors differently than the lighter colors.
BTW, for those interested... here is an image of how the display controller within latest AMD GPU series handles color correction (e.g. sRGB -> wide gamut). It now converts to linear RGB first.

http://images.anandtech.com/doci/3987/ColorCorrection2.png

JanWillem32
10th December 2010, 11:48
That picture should only apply to color profiling unaware programs, where the standard engine from the video card completely takes over the color management. If indicated by a program, many of those functions can be disabled or changed. I tested this with MPC-HC, and indeed, many of the items listed in the control panel don't work at all when I play a video. It will however take some time before the color engine in MPC-HC matches the quality of the one in Photoshop. I'm already glad it passed the test with the R and G inverted test profile.
I do like that system with de-gamma, as you can see in my post from yesterday. I de-gamma for a lot of the RGB-mode shaders, and then I have to invert it again at the end, or else the color correction fails. Linear RGB is just an easy format to make compare and interpolation schemes for.

CiNcH
10th December 2010, 18:35
Short chroma upsampling comparison with my HD 3650

Sample: Bronzés.mkv (720p H.264)
Decoder: ffdshow-mt
Renderer: MPC-HC EVR Custom Presenter (Nearest Neighbour)

ffdshow NV12
http://members.inode.at/762450/chroma/nv12.pnghttp://members.inode.at/762450/chroma/nv12_chroma.png

ffdshow YUY2
http://members.inode.at/762450/chroma/yuy2.pnghttp://members.inode.at/762450/chroma/yuy2_chroma.png

ffdshow RGB32 HQ
http://members.inode.at/762450/chroma/rgb32hq.pnghttp://members.inode.at/762450/chroma/rgb32hq_chroma.png

ffdshow NV12 + Jan's 4:2:0 Chroma Upsampler
http://members.inode.at/762450/chroma/nv12_chroma_shader.png

JanWillem32
10th December 2010, 19:28
Thanks for those very clear samples, they even show a better representation of the two types of the problem (4:2:0 and 4:2:2).

I have some good news and some bad news.
The bad news is, that one of my experimental shaders proved that MPC-HC has a bug. I used the following shader:
sampler2D s0 = sampler_state{MipFilter = None; MinFilter = None; MagFilter = None; AddressU = Border; AddressV = Border; BorderColor = 0x111111;};

float4 main(float2 tex : TEXCOORD0) : COLOR{
return tex2D(s0,.125*tex);
}

That proved that either MPC-HC or my video card's driver ignores the given sampler states. As my reference renderer does properly project the texture on a teapot with the given sampler states, it seems likely that it's a problem with MPC-HC.
This bit of code does compile without errors within MPC-HC, and I can't see anything wrong with the compiler code output.
This shader does nothing more than magnifying 8× with nearest neighbor. The problem is, "MagFilter = None;" should disable any texture filtering (bilinear, trilinear or anisotropic), but in MPC-HC the filtering is forced. I was already wondering why my shaders didn't improve with different sampler states. I also tried down-scaling with this shader, by changing ".125" to "1.5". "AddressU = Border; AddressV = Border; BorderColor = 0x111111" should then give white borders where there once was a texture, but it doesn't work.
Changing settings for the renderer, video scaler or video card driver didn't change anything.
Can anyone test this as well? I will need to make a bug report if everyone has this problem.

The good news is, once this bug is solved, the quality of some my shaders could improve quite a bit, especially the scaling types. Until then, I will only have my reference renderer to test the shader quality. :(

CiNcH
10th December 2010, 22:19
How about integrating the scalers the way bicubic is integrated into MPC-HC CP? The rendering engine then handles these things..

I now tried Catmull (again with DVD content upscaled to 1080p). It is a bit more blurry compared to Bilinear but a lot better than your Lanczos2.

JanWillem32
11th December 2010, 00:57
I wonder if that would solve it, as it's still a shader, and it remains in the same rendering environment.
The shader is blurry because the sampler it uses is forced to filter 4 to 64 pixels per sampled pixel, depending on the depth of the forced trilinear/anisotropic filter. An unaltered input (as requested by the sampler state) would be much better for performance and accuracy.
I do want to remind everyone that the shader doesn't iterate automatically, so it can't scale up or down more than 2 times. Use the "2×" version and the regular version on top of that to be able to scale between 2 and 4 times.
Right now I'm in the process of trying to bypass the automatic filters by either trying to set environment variables or by using texture loading to memory. It's really not my cup of tea to try to bypass this problem, as I'm completely in the dark why it's happening in the first place.

Edit:
Upscaling video content with non-square pixels doesn't work with that pixel shader either. Video content from most DVD's will always look wrong when scaled by that shader. I will add a version can split scaling for width and height.

Edit:
The "test 13" batch this time, with 42 shaders. :) This includes new shaders, among those shaders is my first version of "semi-random grayscale noise". It looks quite the same as the original version, but it's a good start.
I really should start recruiting beta testers, testing all the normal and experimental shaders under various conditions is taking too much time and effort. Not to mention that English is only my third language, so I need to carefully re-check grammar and spelling for the names and comments. I rather work on the experimental types and get them to function. :rolleyes:

Edit:
I added some comments and made the scalers work properly. "Spline6" (square root of 36) now resizes with the regular sharpness, including the ringing artifacts. Be careful when filtering in combination with that shader, over-sharpening isn't pretty.

CiNcH
13th December 2010, 19:58
Hi Jan,

please don't edit old postings. It's really hard to follow then..

So if I want to upscale anamorphic DVD to 1080p, I have to do the following...

Stack the shaders 'Catmull-Rom Spline6 width resizer' and 'Catmull-Rom Spline6 height resizer' in screen space and edit them the following way:

#define Magnify (1920/720.)

resp.

#define Magnify (1080/576.)


Is that correct?

[EDIT]
Result seems to be too wide, horizontally stretched too much, cutting of parts of the image to the left and to the right.

CiNcH
13th December 2010, 20:37
#define Magnify (1920/1024.)

and

#define Magnify (1080/576.)

seem to give me correct results. Output pretty much looks like a bilinear filter.

JanWillem32
13th December 2010, 20:47
Don't forget that if anamorphic correction is enabled, the internal resizer will still be used. If you disable that one too, (1920/720.) and (1080/576.) are correct.
Anamorphic correction is under View, Video Frame, "Keep Aspect Ratio".
I've had some very good results with Spline6, it should really not look like bilinear filtering, even when the forced sampling filtering bug is still present. Can you compare 400% with Spline6, Spline4 and some default scalers? It might be a problem with my shaders after all.

CiNcH
13th December 2010, 21:15
Anamorphic correction is under View, Video Frame, "Keep Aspect Ratio".
OK, result is now comparable to Bicubic with Spline6.

Can you compare 400% with Spline6, Spline4 and some default scalers?
Doubling the size + pan&scan does not give me the same result with your scaler vs. default scaler (like Bilinear).

JanWillem32
16th December 2010, 18:13
It's been a while since I last posted, so here's the test 15 batch. I mostly fixed minor errors, and I finished the other old film effect shaders to accompany the noise shader. I can merge all or some of the film effect shaders later on, if that's preferred.
At the moment I'm searching for the bug in the shader environment code that forces the sampler states to use filtering. I already found the main resizers, effect shaders and color control/final shader at: http://sourceforge.net/apps/trac/mpc-hc/browser/trunk/src/apps/mplayerc/res/shaders.
Once I know a bit more about the bug I will make a support ticket, with some references of how to solve it.

I would appreciate some feedback from testers about the usual performance with my shaders in different environments. I currently only use my standard (game-orientated) shader editor and MPC-HC with EVR to host the shaders. Other projects that could use a few new shaders are definitely welcome too.

TheElix
17th December 2010, 13:54
semi-random grayscale noise.txt - is this the "BD grain" filter? Unfortunately it doesn't add to the detail of the picture. With its current state it seems more like an interference. Maybe it's too intense? Or maybe it'll never be able to enhance detail like the real BD grain.

As for hybrid shader here's my usual portion of comarisons:
1) On HD anime content: http://screenshotcomparison.com/comparison/12394
While it looks sharper and nicer at first you may notice that there's a huge loss of detail in the grass and in the mountains. It's like lowering the bitrate of a video considerably which is unacceptable.
2) On HD real-life content: http://screenshotcomparison.com/comparison/12402
There's a loss of detail in the shadings. Look at her palm and the area around her mouth. A lot of transient colors in that area was lost and it looks bad. Almost like a scrub, lol.
3) On SD real-life content: http://screenshotcomparison.com/comparison/12404
Again, there's huge loss of detail everywhere: on her skin, her clothes and in the background.

I hope this doesn't strike you too hard) I was only testing.

JanWillem32
17th December 2010, 15:11
Thank you for the comparison. First of all: what's the "BD grain" filter? The "semi-random grayscale noise" was modeled to evenly add or subtract brightness, randomized per pixel, and evenly as much on dark and bright patches. I re-designed most of the shaders that rely heavily on the RGB contrast to require linear RGB gamma, including this one.
What kind of noise generation adds detail to a picture? All of the examples with other filters that I've seen either do the same thing as my shader (grayscale per-pixel random noise) or add grain of a certain size (a bit like my dust shader with some altered settings). Neither is beneficial to the detail level.

For the pictures: all three pictures have below average noise. 1 is synthetic, this will require minimal noise filtering (maybe even a bit lower).
2 really requires pre-processing to convert the picture to linear RGB gamma, and mild noise filtering. This picture has a large contrast. Unfortunately video contrast (BT.601 and BT.709) is linear for low brightness, and has gamma scaling above a certain point of brightness. That makes direct RGB fltering with the same weights for darker and lighter areas impossible. See this website for the video gamma function (at number 9): http://www.poynton.com/notes/colour_and_gamma/GammaFAQ.html
3 is really low resolution (interlaced NTSC?), it rather needs a good scaler than sharpening. It can be sharpened by "sharpen complex v3 + deband + minimal denoise" in screenspace after scaling. It will be hard to find the right set of filters for this picture that do sharpen, but don't accentuate staircasing artifacts because of the scaling.

I hope you can test again. If required, I can change a few functions. The "semi-random grayscale noise" will probably need a bit of work, or a second shader to with a different type of noise (if I can find an example how it should look).

Jong
17th December 2010, 15:22
The video file to display path in Windows requires Y′CbCr data to be converted to RGB, even if data is converted to Y′CbCr for DisplayPort, HDMI or dual link HD-SDI transport. Hi Jan, only just found this thread after a while away.

Are you sure this is always true.

What about the "EVR onto overlay surface" used by the "commercial players", used mainly for Blu-ray, but also for DVD in TMT?

I ask because some months ago it became clear over @AVS Forums that this 'special renderer':

a) allows BTB/WTW for Blu-ray, when all other players end up clipping during RGB conversion, even if YCbCr is eventually output.

b) This renderer also fixes a slight "Green push" error at low lunminance, when using YCbCr that AFAIK is still present in the latest ATI drivers for 5xxx. This "green push" was assumed to be introduced during RGB -> YCbCr conversion, as it is not present with RGB output.

JanWillem32
17th December 2010, 16:04
As long as no DirectX surface/texture format is used, Y′CbCr can be exported directly to the video driver (with some flags set). That does disable any other blending, such as subtitles, color correction, filters, etcetera. It also can't use that many scaling modes (for both chroma and luma). Further usage of the videocard is limited, as there are not a lot of pure Y′CbCr mode filters/shaders. If any blending does happen with the picture, then it's converted to RGB in between, the video driver can force such a conversion in the end stages of video processing as well. The video card driver will always use larger processing formats than 8-bit integer, if possible. That can influence things too.
As I stated before, I don't know what method of range limiting is used in the ATi drivers. There's a difference between RGB value compressing (like the original shader) and Y′&CbCr value compressing (like my shader). If there's a green push, then it's likely the former.

TheElix
17th December 2010, 16:30
2 really requires pre-processing to convert the picture to linear RGB gamma, and mild noise filtering. This picture has a large contrast.
Ugh. Is this better? =\ I'm not sure. http://screenshotcomparison.com/comparison/12459
Maybe I got the wrong conversion shader.

So you're saying each video needs its own approach? It's only natural, I suppose. But from a user's point of view that'd be a nightmare - to pick up new shaders each time you watch a different video. That is assuming you want to get a better picture. It makes me wonder if you can enhance it at all using these means. Maybe it's a better idea to leave the enhancement thing to studios and watch videos they were produced? Not saying that your or others' work is meaningless. On the contrary, video rendering technologies improved substantially thanks to the likes of you. I'm only saying that these shaders thing is more for the guys who understand video processing deeper than common users.

JanWillem32
17th December 2010, 20:04
That filtered picture looks perfectly OK, if I view it in Photoshop with a linear RGB input setting.
You got the right conversion shader, but maybe I forgot to tell that the "gamma conversion of linear RGB to HD&SD video RGB" shader, should then be added at the end of the filter chain (can be used in screenspace). If you use a display calibrated to sRGB or wide gamut RGB, you can use a different conversion shader for output, video gamma output is more something to use in combination with the lCMS color correction function or uncalibrated Y′CbCr mode over DisplayPort or HDMI.
The simple shaders and Y′CbCr-type shaders are made to be used stand-alone. However it's bad for the performance of the Y′CbCr-type shaders, it's more convenient for the user if there's only one or two shaders in use.
It's indeed true that the more complex shaders are a bit harder to configure. In games, it's very common that a single pixel will be handled by more then 20 different shaders before output (multiply that by 10 to 100 for ray-tracing filtering). In video processing, I would have to write a manual for most people to understand how to make proper shader chains, so I try to combine functions.
At first I said that people should even enter the "NoiseLevel" value manually. Later on, I just created 5 basic profiles, with only the "NoiseLevel" value changed.

As for switching, I personally don't hate it. I use chains of up to 8 shaders, and I switch them with simple .REG registry profiles. I already stated that activating and switching shaders within MPC-HC is harder then editing the registry, so the program could use a bit of improvement in the GUI. Maybe an item for shaders in the options screen, combined with decent descriptions of what they do and how to use them would be welcome. Y′CbCr- and linear RGB-type shaders could then also be placed automatically into the right category where they receive a correct input by default. Profiles of shader chains, with some default examples would be useful, too.
Seeing that the default end-stage shader also executes the lCMS color matrix, I think that function could be added as a selection for the end-stage shaders. (The absolute last function should be the "0-256 to 16-235 for SD&HD video input" shader, if it's really required.)
On top of that, don't forget that the default scaling functions are handled by 2 stacked shaders, as well.

I agree with you, the use of shaders could be easier, but I completely disagree to let studios/distributors handle things...:
http://theabyssgazes.blogspot.com/2010/03/teal-and-orange-hollywood-please-stop.html
http://en.wikipedia.org/wiki/Loudness_war
http://www.cracked.com/article_18664_5-annoying-trends-that-make-every-movie-look-same.html

Not to mention the terrible encoding settings I've seen that distributors use for DVD/Blu-ray audio and video. Even worse, DVD's/Blu-ray's from a tape master from video that was shot and/or edited in a digital format.
I'm wondering when they start realizing that 4:2:0 sub-sampled chroma, 8-bit color, interlacing, compressing dynamics, etcetera, are all lowering the overall quality compared to the master, even before the lossless/lossy compression scheme can do it's work.

bobdynlan
17th December 2010, 21:35
I finished the other old film effect shaders to accompany the noise shader. I can merge all or some of the film effect shaders later on, if that's preferred.
After your initial reply I thought that you did not get it and I was thinking to recode it myself, as you've misunderstood the comment on your first look (it was about the noise banding i.e. the random noise algorithm was too limited and generated visible patterns from time to time and that's why I've added the variable at that time).
And now, Bull's Eye! Just what I asked for, a recode that's mathematically sound and outputs the same effect. And a proper name for it, too as "semi-random grayscale noise" best describes it - but not the best "selling" one. What could potentially improve it will be higher displacement and a variable size, as it is now too uniform and per-pixel like. I'm even considering replication of bad hdmi cables coupled with plasma display - you know that discreet red noise. Someday...

For the people that did not understand the purpose of this (unfinished) effect, think about it this way: a print can be outstanding, but will never match an oil paint. Why is that? - Because of the flatness and perfectness a print has vs. the 3d layered nature of the oil paint. You can move around it and discover new details, if the light changes you discover other details and so on. Most of those details may have been inherited flaws of the technique but you see them as part of the art. A parallel can be made to studio(tv) versus film. Grain was a flaw in the technique as well, but become part of the art. To hell with studio-like dull pictures wasting space on a blu-ray disk being encoded with lame noise killing parameters and being watched on a lame LCD. Praised be da' Noise, so say we all. It's not there yet, but it helps. It does not improve detail? Try watching some gaga doing telephone - you'll find out she definetly has a d*ck! Joke aside, any movement added on large static areas does just that. But you have to watch it from a suitable distance, and try not to search for it at the beginning... you will get used to it. It must be run as a screen space shader, try a higher NoiseStrength (.10625 magically matched my preference on the old shader).

About the other shaders, TheElix has some point. It's true that it cannot be perfect, because you cannot detect objects from a still alone, you need to consider motion. The only way to fix issues will be a temporal approach, that is to analyse multiple frames and that is a halt. Let's stick with what we've got, MPC-HC with customizable shaders and a one JanWillem32 that brought a consistent contribution on the matter.
Thank you.

JanWillem32
18th December 2010, 00:00
Well, I have to thank you too. I could not use the regular noise functions for snow, smoke, fog, dust and scratches, as these use pre-rendering and/or DirectX 10/11 functions. The randomization method was quite a useful template for the film effect shaders. Snow, smoke and fog will need a bit more work, but those are not priority (just special effects). I can take a look if I can make another version of the noise shader that has a preference for a less extreme minus to plus contrast variance distribution. I will definitely raise the default NoiseStrength to a binary rounded fraction near .10625 (7/64. maybe). I already raised the value when I demonstrated it with the old film effects, to make the effect look "authentic".
As for temporal functions, it can be done, but it does require 4 complete texture framebuffers (two past, two future, often with the native 128 bit per pixel color format) for 1 iteration (6 for 2 and 8 for 4). That's 4*128*1920*1080/sqr(1024)=1012,5 MByte of memory throughput per processed 1080p frame. It's 759,375 MByte if alpha (multi-layer translucency) blending is disabled. It also needs vertex and maybe some geometry shaders if it's meant to be handled in realtime on the shadercore, and even then the output has to be re-synchronized because of the buffering. Advanced frame interpolation is a popular temporal filter type. But as many might know, it's one of the heaviest types of video filters. To take that kind of filter to GPU processing in realtime, it will require a recent performance model video card, in most likely a DirectX 10 or 11 D3D fullscreen exclusive mode.

CruNcher
18th December 2010, 13:53
To take that kind of filter to GPU processing in realtime, it will require a recent performance model video card, in most likely a DirectX 10 or 11 D3D fullscreen exclusive mode.

doesn't fft3dgpu implements a temporal sharpening (dx9 shader) ?

JanWillem32
18th December 2010, 20:04
I looked it up, fft3dgpu uses YV12 (12-bit per pixel planar format) input and output. A bit odd, since the internal calculations can use 32-bit floating point per component. By default, it only processes luma. I wonder how it solves the hue and saturation problems I encountered when using independent luma sharpening on sharpen complex v3. I chose to use independent processing of linear R, G and B with equal weights in the end to make a uniform appearance.
I must say, using an additional .DLL to make some threads for the CPU to work on, is quite a smart way of offloading some tasks.
For my example, I was thinking about a windowed 4-frame method with motion adaptation for frame interpolation (one of the most common methods), sharpening kernels are a bit simpler. Still, the memory requirements per frame I stated are still valid. (I would not recommend to do FFT transformations in a limited 16-bit floating-point format.) Even on the default (low) settings, running fft3dgpu in realtime currently requires a fast system to handle up to 1080p video.

G_M_C
19th December 2010, 22:34
JanWillem;
Is there any way to strip away FFT3DGPU to it core, so it just functions as a vehicle to drop an hlsl script into an Avisynth script ?

(i.e. just leave the core so you can use whatever .hlsl you want and the core just feeds&reads frames etc. That way it would become somewhat of a universal GPU filter.)

JanWillem32
20th December 2010, 01:43
That's possible, but the environment settings, input registers and function calls to the (very complex) HLSL file are locked by the .DLL file. It won't be easy. If someone would like to start on a project like that, it might be more worthwhile to use the DirectX 10//11 input template and program an Avisynth link for it. That might do the trick to execute in realtime with some performance on various (layers of) complex shaders. If the environment settings, input registers and function calls are then set to generic modes and input modes from the script, it should then be capable of running all kinds of shaders.

tetsuo55
20th December 2010, 08:45
Janwillem, any chance of you digging into the bug mentioned here http://forum.doom9.org/showthread.php?p=1463148#post1463148 , and providing us with more detail so we can fix it?

JanWillem32
20th December 2010, 09:37
Sure, I've already tried to find the source code that hosts the shaders to try and point out the specific code to update. So far I haven't been very successful.
As a reference, this is what the sampler states are supposed to do:
http://drzovil.blogspot.com/2007/04/texture-filtering-modes.html
It turns out that some other programs tend to force those parameters too:
http://efreedom.com/Question/1-2700041/HLSL-Can-Set-Sampler-Min-Mag-Mip-Filters-Disable-Filtering-Anti-Aliasing
If it takes only one line to solve this problem, like in the above example, it shouldn't be too hard to do something about it.

Deshi
20th December 2010, 09:42
Hi everyone !

I would like to have some insight about shaders chain.
I'm corrently testing this chain :

16-235 to 0-256 for SD&HD video input
4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input
SharpenComplex v2 + Deband + Medium Denoise
SuperResolution
gamma conversion of linear RGB to HD&SD video RGB

with moderate satisfaction. I'm wondering if I 'm using the shaders in the correct order ? I'm using the bicubic scaler of the renderer because I can't find where to put the Spline scalers in the chain :confused:

I totaly understand that you can't comment every chain that everyone could use but would it be possible for you just to give us a guide line ?
Something like :
these shaders (x, y, z) must go first/middle/end...
these shaders (x, y, z) must go before/after these...

I've read attentively your comment in every shader but I'm such a newbie in this that I don't understand much...

Thanks

JanWillem32
20th December 2010, 10:37
For regular SD&HD video input, the following shader order is correct:
-input video
~~~"for SD&HD video input"-type shaders (these use Y'CbCr mode)
~~~"gamma conversion of HD&SD video RGB to linear RGB" shader
~~~regular shaders
-screenspace renderer
~~~scaling/resizer shaders
~~~regular shaders
~~~"gamma conversion of linear RGB to"-type shader*
-video output

*Use the "gamma conversion of linear RGB to sRGB" shader for sRGB standard display devices.
*Use the "gamma conversion of linear RGB to wide gamut RGB" shader for wide gamut RGB standard display devices.
*Use the "gamma conversion of linear RGB to HD&SD video RGB" shader for display devices:
- with a calibrated .ICM display color profile installed system-wide and color management option in the program enabled.
- connected with Y'CbCr mode over DisplayPort or HDMI.
- with a very specific need for a BT.709 or BT.601 derived RGB input.

**The "0-256 to 16-235 for SD&HD video output" is an exeption, it needs HD&SD video RGB input and it has to be placed at the very end of the chain of shaders, and only without any further software color management or video card driver-based color correction.

Deshi
20th December 2010, 10:47
Waow !

Thanks a lot for the quick reply !

The difference you make between "input/screenspace/output" shaders...
Does it mean that I have to choose if I use them as input or screenspace ?
Does it mean that they be combined all together in the combine option for shaders in MPC-HC ?
Is there a different "place" to put the screenspace shaders ?

Thanks again...

JanWillem32
20th December 2010, 11:56
Shaders that run on the video input texture run at the video FPS with the same height and width as the source video.
[Currently not implemented in MPC-HC, but is a future possibility.] Screen resolution shaders run on the video FPS with same height and width as the output display resolution.
Screen space shaders run on the screen refresh rate with same height and width as the output display resolution.

In the main comment line 2 (and 3 for the scaling shaders), I indicate if a shader can, should or should not be used in screen space.
Running a shader in screen space is usually much heavier, by the way. Many displays are locked to 60 Hz. That means that the shader is then executed 60 times for every output pixel per second when used in screenspace. The shaders that run on the input video texture typically run at 24000/1001 to 30000/1001 frames per second, depending on the input video FPS.

Screen space shader slots are available under the "Combine Screen Space Shaders..." option. It can be active simultaneously with the shaders under "Combine Shaders...".

tetsuo55
20th December 2010, 13:53
i tried browsing the code but i too cannot find where this stuff is happenng...

JanWillem32
20th December 2010, 14:11
Which part of the source code even sets up the standard sampler and registers? By default, the environment registers are empty. Something is setting up the registers containing basic metrics, framecounter, clock, pixel size and texture sampler. I have been looking at far too much code, and found absolutely nothing yet.

clsid
20th December 2010, 22:51
A quick search reveals that most shader related code is located in the VideoRenderers part of the solution file. For example the resizer is in DX9RenderingEngine.cpp.

JanWillem32
20th December 2010, 23:28
Thank you, that's indeed the DirectX 9 host. It's rather far away in the folder structure... (I didn't look that far, my bad.)
Ignoring the forced sampler states for the dithermap and 3D color correction space for now, the regular sampler states start on line 1661. As far as I can see, lines 1661 to 1666 can simply be commented out. The given states (Linear interpolation and texture border Clamp) are the defaults for the DirectX 9 engine anyway, so if a shader doesn't specify any sampler states, it will simply inherit the same sampler states as it currently receives from the engine. By the way, if textures are handled in pure 2D mode, forcing mipmap generation to "None", can be very useful in preventing extra work for the GPU. (Mipmaps are used for anisotropic filtering on textures that are displayed with a z-angle.)

While I'm at it anyway, why is "full floating point processing" specified as fp16 RGBA? In my book, a full floating point is fp32, a half is fp16 and a double is fp64. On top of that, shaders will use fp32 mode on textures/calculations anyway, unless the "partial precision" flag is set. (Even if that flag is set, it's ignored at least in my case: http://forum.doom9.org/showthread.php?p=1461777#post1461777 . My GPU probably doesn't even have a half-precision pipeline.) I don't know if a method of constant switching between fp32 and fp16 mode is beneficial for performance when large textures are loaded and unloaded up to 200 times per second. (It's a different thing in games where many loaded textures are often used for several hours.)

tetsuo55
21st December 2010, 10:23
Is it within your capaibilities to make a patch to fix what you found?

JanWillem32
21st December 2010, 12:39
For both, I'd have to edit the lines and compile.
I'm not so worried about compiling with lines 1661 to 1666 of DX9RenderingEngine.cpp disabled/removed. The DirectX reference documentation is quite clear on inheriting the default rendering and sampler states, if it's not overridden by other code.
For the other item I had to search a bit, because I'm mostly working with DirectX10 and 11. The DirectX 9 rules are a bit different, and I don't remember everything from when I was educated on this subject. A basic search confirmed what I already thought:
http://www.robertwrose.com/2005_05_01_robertwrose_archive.html
"Currently only floating point textures are supported by today's vertex shader hardware, so the data needs to be stored in one of these formats:

D3DFMT_R32F: 32-bit float format using 32 bits for the red channel.
D3DFMT_A32B32G32R32F: 128-bit float format using 32 bits for the each channel (alpha, blue, green, red)."

That is quite logical: look inside some pixel shaders, the main function and return type are "float4". That means that any texture that goes trough the shader pipeline will have to be converted to fp32. I do know that there's a trick with using partial precision mode, but that only works on the calculation format, not the texture in process.
With DirectX 8 and older hardware, the surface formats were locked to the display format, so A8B8G8R8 was the largest processing format available if 32-bit color was the display format. There was no support for floating point surfaces.

I would have to test if setting D3DFMT_A32B32G32R32F as surface format improves performance because of not having to convert between fp16 and fp32 textures. It could also very well be that with some types of older hardware texture swapping occurs, and memory speed becomes an issue. I don't think that's likely, by the way. (Even the cheapest GPUs have huge amounts of L2/L3-like cache to store big chunks of textures and vertices in.)
http://developer.amd.com/media/gpu_assets/R2VB_programming.pdf
That document indicates that the D3DFMT_A32B32G32R32F format has been used as default since the earliest DirectX 9 hardware, the Radeon 9500. (Too bad I couldn't find anything from nVidia, they usually have good documentation of the hard- and software capabilities, too.)

bobdynlan
21st December 2010, 12:47
That was funny, MPC-HC it's not such a big mess, your comments are scaring people away :devil: "texture" keyword should have nailed it down.
While I'm at it anyway, why is "full floating point processing" specified as fp16 RGBA? In my book, a full floating point is fp32, a half is fp16 and a double is fp64.Marketing...
True, it's not the best choise, it should be fp24, as that's the highest precision you can get that works on all dx9+ gpus. It's only alpha that's missing, the color bits are all there. My 9800pro was fp24. nvidia did support fp32 at that time, I guess it will make a better platform for this kind of work. I remember reading not so long ago about ati "optimizing" fp16 by halving the bits, and that may be a reason for the mixed results people are getting now.
Anyway, this feature is more of a overkill until higher bit panels become mainstream.
[EDIT]
If you’re using wide data types the bandwidth required for this could become a bottleneck. Also keep in mind that wide data types not only require extra bandwidth, but also need additional cycles when you sample them in the pixel shader, even if all data is in the cache. An RGBA32F texture requires 4 cycles per sample, whereas RGBA16F only requires 2 cycles. With the
Radeon X1900 and Radeon X1600 providing a 3:1 ALU:TEX ratio in pixel shaders it becomes increasingly more important to keep the amount of cycles spent on texture sampling down.
From that doc. Keep in mind that it's refering to X1xxx hardware.

tetsuo55
21st December 2010, 12:56
Interesting stuff!

Quality should come first, and performance second. (although its always a good idea to support a mode with lower quality and higher performance)

@bob > higher bit panels = more than 10bit?

bobdynlan
21st December 2010, 13:14
Higher than 6 :) Most people have shitty TNs.

It compiles fine without those presets and it works as usual at runtime with all the Presentation options and shaders enabled.
[EDIT]
Magnification shader seems different with the new build... for the naked eye. Maybe it's placebo...
Down-scaling does not create white borders on my system on both builds, instead repeats the last pixel until it reaches the screen border. Hmm, I don't have a proper sample to observe the filtering, but it seems it's not enough to fix the issue (again, naked eye).
[EDIT2]
Comparation: Left is the new build
http://img156.imageshack.us/img156/5203/38703114.png:cool:

JanWillem32
21st December 2010, 14:25
Well, I'm probably a scary programmer..:p (I know I should spend more time on creating regular shaders. At the moment I'm only testing a new sharpening method/filter.)

The fp24 calculation format exists, but it doesn't have a equivalent surface format.
Currently D3DFMT_A16B16G16R16F surfaces are used in MPC-HC when "full floating point processing" is enabled. The standard fp16 only holds 10 integer bits, so it's already not much to go with if you want to use dithering for the A2B10G10R10 display format. Two whole bits of overhead over the X8B8G8R8 format should be fine when dithering for just 8-bit output.
When I saw the format section in the source code, I was wondering why D3DFMT_A16B16G16R16F was used exclusively. When working with heavy HDR rendering, floating point surfaces are required for the lighting effects. For real-time rendering, it's usually a mixture of fp32 for critical or heavily shaded surfaces, and fp16 or less for "background".
When sampling a texture, it does quite matter if alpha blending, mipmap generation, anti-aliasing and anisotropic filtering is disabled. That's all quite normal to disable if you're working in 2D only. The sampling of textures only requires one unfiltered input pixel per sampled pixel in that case.
Sampling textures becomes harder in 3D games due to the usual filtering that requires multi-sampling to render a single pixel (from a few layers of alpha-blended textures). That's why the documentation warns to not sample too many points for each shader. It eats up a lot of memory resources to supply a single shader unit with many pixels at once.

It's good to know that the sampler states can probably be reverted to the defaults.
Can you also take a look at lines 120 and 121 that force "clamp"? I don't now if the entire block of sampler states should be removed or "D3DSAMP_ADDRESSU, filter" and "D3DSAMP_ADDRESSU, filter" should be inserted.

bobdynlan
21st December 2010, 15:11
Maybe D3DTADDRESS_BORDER is what you need? My experience in this field is next to none...

While you are at it, maybe you can take a look at the issue with 10bit output mentioned by Mercury_22. First not-working rev 1826. Back then mpc-hc had another layout, I guess DX9AllocatorPresenter.* was all-in-one, now DX9RenderingEngine.* is branched from that?!
http://mpc-hc.svn.sourceforge.net/viewvc/mpc-hc/trunk/src/apps/mplayerc/?pathrev=1825

JanWillem32
21st December 2010, 15:51
DX9RenderingEngine.cpp, lines 191 to 196 allow detection for 10-bit support. The problem with 10-bit is that it requires exclusive mode with this kind of implementation. See also: http://msdn.microsoft.com/en-us/library/bb172558%28v=VS.85%29.aspx

The older source code didn't include detection. If it was enabled (forced) back then, it either worked or blanked the screen. Right now, I'm guessing the detection is done outside of the exclusive mode, so it always returns negative. A good first step would be to test if 10-bit output can be forced again, to see if it still works. I don't know the exact syntax to force "succes" out of lines 191 to 196, however.
Enabling 10-bit again would be very nice indeed. In the past I've successfully used it with MPC-HC, and I still use it with Photoshop.

tetsuo55
21st December 2010, 15:57
Awesome work so far guys!

From what you guys have been posting here it looks you are going to fix up to 10 bugs with regards to performance and image quality for "scaled" video!
:thanks:

JanWillem32
21st December 2010, 16:20
...:D Well, right now I haven't actually produced anything but a few half-baked pixel shaders. But with some luck, and a lot of help from some skilled people, we might just produce something useful.

As for lines 120 and 121:
hr = pD3DDev->SetSamplerState(i, D3DSAMP_ADDRESSU, filter);
hr = pD3DDev->SetSamplerState(i, D3DSAMP_ADDRESSV, filter);
It could also very well be that the entire block 115 to 122 is useless.
All entry's of "D3DSAMP_MIPFILTER" can be set to "none" if the work is done on pure 2D space, by the way. That might improve performance when a shader doesn't exclude mipmap fitering in the sampler state. -Correction, for DirectX 9, the default value is already D3DTEXF_NONE.

bobdynlan
22nd December 2010, 17:50
You can't just comment the whole block, because there are some other stuff involved. For example the OSD needs linear filtering or else it looks bad. So it needs to be patched case by case.
I do remember image looked sharper some time ago. These pictures prove that an extra filtering step it's being applied. First two compare the nearest neighbour, last two bicubic -1, 16x(double window + test resize shader).
http://img149.imageshack.us/img149/3118/defaultnearest.th.png (http://img149.imageshack.us/i/defaultnearest.png/)http://img232.imageshack.us/img232/7791/patchednearest.th.png (http://img232.imageshack.us/i/patchednearest.png/)
http://img836.imageshack.us/img836/6718/defaultbicubic1.th.png (http://img836.imageshack.us/i/defaultbicubic1.png/)http://img69.imageshack.us/img69/8595/patchedbicubic1.th.png (http://img69.imageshack.us/i/patchedbicubic1.png/)

JanWillem32
22nd December 2010, 19:26
If the OSD is handled by a pixel shader, it can specify linear interpolation for up- and downsizing by the sampler in the shader code:
sampler2D s0 = sampler_state{MagFilter = Linear; MinFilter = Linear;};
(Or whatever sampler addressing instead of s0 is used in that case.)

This webpage points out the default sampler states:
http://msdn.microsoft.com/en-us/library/bb172602%28v=vs.85%29.aspx
Unless some fancy type of effect filtering has to be forced for all shaders, I don't think any of the defaults should be overridden in the main code.

It's good to see that the test shader is working as it should. Next time, do avoid the "double window" setting, it's not that pretty to see two filtering methods combined.

JanWillem32
24th December 2010, 14:09
To do:
-Try to compile a program with a GUI for the first time...
-Try to do the same with MPC-HC, for testing purposes.
-Test to see if the most recent shader compiler can be included. (The current version is 9.29.952.3111, http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=3021d52b-514e-41d3-ad02-438a3ba730ba&pf=true indicates that the most recent version is 9.29.1962.)
-Test to see if there's any quality degradation with the default scalers, if the shader sampler states are reverted to the DirectX 9 defaults. (That's unlikely, as the code of the default scalers isn't bad at all.)
-Test to see if any other shader components require updating (e.g. the current dithering and color correction shader).
-Test the difference in performance with standard fp16 and fp32 surface formats.
-Force the code to allow 10-bit RGB output to the display.
-Make proper detection code for the 10-bit RGB output mode.
-Submit a support ticket concerning the exact lines of code that have to be altered to make shaders work properly, including sufficient explanation.
-Submit a support ticket concerning the HLSL shader compiler.
-Submit a support ticket concerning code updates to make the 10-bit RGB output mode work again.
-Submit a support ticket to ask which shaders are interesting enough to include in the source.
-Have a merry Christmas and a happy new year.

For the people that I've scared with my techno-babble the past few days:
My normal shaders are quite easy to use once you know how to copy-paste them to the compiler screen.
I always include a few lines of comments for when to use a specific shader and what it generally does, without the techno-babble. If any of the comments need an improvement, please let me know.

I did a lot of work on the shaders this time. The shaders are now ready to work with the default sampler states. Once the sampler states are reverted to default in the program, the biggest improvement will be with the performance of all shaders. For "projector film shaking" and "wave" there will also be proper rendering of the black borders.

CiNcH
24th December 2010, 14:59
It seems you removed your first chroma upsamplers? Quality was quite good at a low GPU usage.

Will the Catmull chroma upsamplers make a big difference quality-wise? How about GPU usage? Seems chroma has to be upsampled in two steps?

JanWillem32
24th December 2010, 16:00
"4÷2÷0 chroma blur for SD&HD video input on old and slow PS 2.0 hardware" is still included, it has everything the old version had, except for the sharpening kernel (that had a "bleeding" problem).
There is a one-step shader called "~4÷2÷0 Catmull-Rom spline5 chroma up-sampling for SD&HD video input", but it has a compiling problem with compiling for PS 3.0 in MPC-HC at the moment. The external shader compiler does take it, and MPC-HC does compile it with PS 2.0a. The problem can probably be solved by upgrading the internal HLSL shader compiler to the newest version.
The quality that the spline chroma up-samplers deliver is subjective, but I like the well-defined chroma borders, even with small details of intense colors. For what I've seen, the ringing artifacts are rare. Also, the color of both surfaces and borders with high chroma differences seemed better balanced, compared to what my first shader produced.
The GPU usage isn't too much with the spline4-type, but the spline5-type does sample 25 pixels and performs 15 spline fittings to produce 1 pixel. I don't know how much much improvement in performance the change in sampler states will give. I will have to test it once I find out how to work with the MSVC2010 compiler.

DottorLeo
24th December 2010, 17:25
Hi JanWillem32! I would try to use your shaders to improve my dvd and mkv (SD) experience but i'm quite new to this. How should the shader filter chain be created?

My final target would be:
1) Upscale the source to 720/1080
2) Denoise slightly (and take care of mosquito noise if it's possible)
3) Sharpen

My GPU is an ATI 5770. Thanks!

JanWillem32
24th December 2010, 18:05
Cater it to taste, but the settings I use currently are:
-If the chroma isn't up-sampled (like with my HD4890 with its current settings), the first step is "4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input", the second is "4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input".
-"gamma conversion of HD&SD video RGB to linear RGB"

In screenspace: (in this thread I already described how to disable the internal scalers completely)
-"Catmull-Rom spline5 height doubler" (my display resolution has more than twice the width and height of all SD material, a combination of spline5 and spline6 is roughly equivalent to spline10)
-"Catmull-Rom spline5 width doubler"
-"Catmull-Rom spline6 height resizer" (with the correct magnification factor for my display resolution)
-"Catmull-Rom spline6 width resizer"
-"sharpen complex v3 + deband + minimal denoise"
-"gamma conversion of linear RGB to HD&SD video RGB" +color profile enabled (you might want to use one of the two other gamma conversion types if you don't have a color profile installed)

I set all of them to compile for PS 3.0. I do have to increase the 2D load GPU clock to 675 MHz. That's still well below the 3D clocks, and it doesn't need a higher voltage than the idle setting. It does heat up my former high-end GPU a lot (the fan is loud).
For HD I can't use the "Catmull-Rom spline5 ? doubler"-type shaders, because of the higher resolutions. On top of that, I will use different denoise presets, depending on the amount of noise present in a video. I adapt the standard "mosquito denoise" and the regular "denoise" in the Catalyst Control Center, as well. My advice is not to overdo on the three of them, they can all blur a lot in their own way.

DottorLeo
24th December 2010, 23:01
Cater it to taste, but the settings I use currently are:
-If the chroma isn't up-sampled (like with my HD4890 with its current settings), the first step is "4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input", the second is "4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input".
-"gamma conversion of HD&SD video RGB to linear RGB"

In screenspace: (in this thread I already described how to disable the internal scalers completely)
-"Catmull-Rom spline5 height doubler" (my display resolution has more than twice the width and height of all SD material, a combination of spline5 and spline6 is roughly equivalent to spline10)
-"Catmull-Rom spline5 width doubler"
-"Catmull-Rom spline6 height resizer" (with the correct magnification factor for my display resolution)
-"Catmull-Rom spline6 width resizer"
-"sharpen complex v3 + deband + minimal denoise"
-"gamma conversion of linear RGB to HD&SD video RGB" +color profile enabled (you might want to use one of the two other gamma conversion types if you don't have a color profile installed)

I set all of them to compile for PS 3.0. I do have to increase the 2D load GPU clock to 675 MHz. That's still well below the 3D clocks, and it doesn't need a higher voltage than the idle setting. It does heat up my former high-end GPU a lot (the fan is loud).
For HD I can't use the "Catmull-Rom spline5 ? doubler"-type shaders, because of the higher resolutions. On top of that, I will use different denoise presets, depending on the amount of noise present in a video. I adapt the standard "mosquito denoise" and the regular "denoise" in the Catalyst Control Center, as well. My advice is not to overdo on the three of them, they can all blur a lot in their own way.

:eek: That's perfect! The true problem with MPCHC is that if you force MPEG2 DXVA acceleration with dvd's there are some problems with menus. Your method should bypass this problem :D

Also is possible to make MPCHC detect SD from HD sources automatically with some rules and use the proper shader chain?

JanWillem32
25th December 2010, 20:35
MPC-HC sets 6 environment data registers for both video input and screenspace shaders.
c0.x: horizontal texture/screen resolution (integer)
c0.y: vertical texture/screen resolution (integer)
c0.z: amount of frames processed since starting the render (integer)
c0.w: amount of seconds passed since starting the render (floating-point)
c1.x: the pixel width relative to the texture sampling range <0,1> (floating-point)
c1.y: the pixel height relative to the texture sampling range <0,1> (floating-point)

The default scaling shaders also receive data of how much each should position and resize the picture. (The color correction and dithering shader uses some extra registers as well.)
I tried to access those registers, but I think those registers are excluded from the normal shader environment. Without those registers, I can only write shaders that automatically scale down to a certain resolution.
I personally use .REG file profiles to switch scaling and noise filtering settings. It's currently a lot easier to switch by writing a shader list preset to the registry, compared to manually switching. I might help the project a bit, so that shader lists can be loaded from presets inside the program, and without having to start playing a video first. (I've never done any GUI design before, so that will be more of a long-term plan.)

tetsuo55
25th December 2010, 20:44
You could join us on IRC, some dev's idle there and can help you create the changes.

server freenode, channel mpc-hc

TheElix
4th January 2011, 18:16
Hi! I've just begun to try out your new batch of shaders and I think I've found a bug:
error X3000: syntax error: unexpected token ';'
In sharpen complex v3 + deband + minimal denoise.txt

Maybe you can help me in this issue. I have this particular BD for testing LCD TVs. On my LCD monitor I have too bright blacks. Let me say that I have set full dynamic range (0-255) in the player MPC-HC, in the video driver, in the decoder - everywhere. And still I get "gray" blacks on some sources.
I tried to fix this with your 16-235 to 0-256 for SD&HD video input shader, however it diminished detail greatly: http://screenshotcomparison.com/comparison/17151
Do you have any advice?

Oh, and concerning your hybrid shader. This time I tested deband and... is this it? Well, I see the difference. Maybe it's the best you can do with a shader. But the difference is not as dramatic as with madVR. http://screenshotcomparison.com/comparison/17153

Here's the video I tested deband with. http://narod.ru/disk/2732005001/Banding_720p.rec709.mkv.html

bobdynlan
4th January 2011, 21:46
Testing banding (as in colour banding) with only gray gradients it's not the best choice, you should try out some anime (cartoons) or some movie with sky, oceanic views.

Please check this thread for some test samples regarding levels: http://www.avsforum.com/avs-vb/showthread.php?t=948496 Try the mp4 samples. Everything is based upon http://w6rz.net/ test patterns.

I guess your issue is with gamma. So you should try a gamma conversion shader, with some custom parameter. It does not work out of the box, you must test different values yourself.

These type of shaders were not made very user-friendly unfortunately. JanWillem32, take a look at this one that I've translated some long time ago from virtualdub's vdshader - Apply gamma correction://ps_2_0 LINEAR GAMMA
/* translated from virtualdub's vdshader:Apply gamma correction */
sampler s0 : register(s0);
#define adjust_gamma 1.5

float3 LinearToGamma(float3 c) {
return c <= 0.0031308 ? 12.92*c : (1+0.055)*pow(c, 1.0/adjust_gamma) - 0.055;
}

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 c0 = tex2D(s0, tex);
float3 c1 = LinearToGamma(c0.rgb);
return float4(c1.r,c1.g,c1.b,c0.a);
} Is it not more familiar to adjust a gamma value like 1.5 than 563/256.0? :cool: I suspect you've used the same "magic constants" to come up with your integers, not?

TheElix, some value less than 1.0 (like 0.8) will work for you with the above shader. Or you could use some of JanWillem32's gamma conversion shaders like the wide gamut RGB to linear RGB and mess with the 563/256. parameter.

JanWillem32
4th January 2011, 23:47
@TheElix I corrected the typo in "sharpen complex v3 + deband + minimal denoise". It's becoming a bit hard to test all shaders, at the moment I've made 93 (revisions not included). Thank you for noticing.
I had exactly the same problem when calibrating my parent's LCD TV. I couldn't get decent black without the "dynamic" (ugly torch) mode. I fixed it by disabling all color controls in the hidden factory setup menu. It now needs a color profile to display properly, but at least I can use the complete dynamic range of the display. I know, that type of setup isn't the most consumer-friendly. Another thing that worked okay for me was lowering the total brightness, while raising the whitepoint settings and contrast. It's a bit different with every device. I just wish every device had a RGB 1:1 mapping-to-panel mode. "16-235 to 0-256 for SD&HD video input" causes clipping in your case, it's best not to use it.
The debanding shader works okay. It's not very fair however to compare it to the dithering engine of MadVR, as it doesn't dither on its own. What you're seeing is simply banding by 8-bit limitations.

@bobdynlan "brightness, contrast and gamma control" is the regular gamma control shader, it's not the hardest one to configure.
"gamma conversion of HD&SD video RGB to linear RGB" is the normal shader to remove gamma from a SD or HD video. It's useful because with linear RGB you can use exact multiplications of color values, while keeping the same contrast impact when working on lighter gray compared to darker gray. That's why I mark some shaders with: "This shader benefits from converting to linear RGB, instead of using sRGB or HD&SD video gamma input directly."
"gamma conversion of linear RGB to ?"-type shaders are for converting the linear gamma to the display gamma format.
The shader you pasted is only valid for sRGB conditions, it's not for HD and SD video.
Nice test patterns, by the way. It's a good for testing constant gamma on output.

TheElix
5th January 2011, 00:00
Thanks, bobdynlan! I've tried this shader and the results lead me off the track, as always. Is this the video I really want to apply any changes to? Take a look...
The End screen. It should be black, right? http://img29.imageshack.us/img29/3831/blacktc.png Well, it isn't. That's why I thought the black levels should be tweaked.
And then here's another black screen that comes after: http://img41.imageshack.us/img41/8952/blackip.png. And it's... blacker than the previous one. It doesn't seem completely black, but if I open this picture in Photoshop I can even spot 0,0,0 dots there. Along with 1,0,4; 5,1,2 etc. And it doesn't look perfect black, it doesn't bland with the black stripes on top & on bottom. I'm not knowledgable in these things. But I'm no dumb either to assume that this isn't about TV or PC levels. That color noise might come from somewhere else. And it's not something you can do about with gamma conversion shaders, right?
It's nasty, btw. It darkens the dark parts but it also brightens the bright parts. At 1.45 it gives me perfect black screen (the last one), but it also over-brights some frames.
The temporary solution I found (if I want to see perfect-black THE END screens, lol) is to decrease brightness. I did it in my graphics card drivers. Brightness set at -2: http://img29.imageshack.us/img29/5163/blackbrightness2.png

JanWillem32
It's not very fair however to compare it to the dithering engine of MadVR, as it doesn't dither on its own. What you're seeing is simply banding by 8-bit limitations.
You're absolutely right. Sorry I even mentioned it.

bobdynlan
5th January 2011, 04:44
JanWillem32, I take no credit as I've only linked the patterns.
I was just pointing out the need for a user-friendly parameter, but now there is no point after seeing your "brightness, contrast and gamma control shader".
It looks very clean and works well, :thanks:
Was easy to miss as your layout is not very well organized. What do you think about this one:http://www.mediafire.com/?bda6xd63czecdvb?

TheElix, you should definitely use that one. But even if it does feel more comfortable adjusting things in mpc-hc alone, on-the-fly, without messing with the by-now-get-used-to desktop settings, color profiles and so on, in the end you need a proper calibration.

For the brightness, contrast and gamma control shader, start by adjusting gray gamma, i.e. same value for RedG, GreenG and BlueG. To make the numbers more meaningful (display settings or calibration software), replace default 1s with 2.2/x.xx where x.xx is the new gamma. Higher than 2.2 will increase midtones, less will decrease them. I guess you need to increase them for detail (ex: 2.2/2.4). Then decrease brightness in .01 steps (ex -0.01) and increase/decrease contrast. Be careful with the contrast, as that can break your previous result quite dramatically, that's why it is better to set it last or not use it. Those patterns will be useful for brightness and contrast, I don't know some available source for gamma. I've re-uploaded one file I've found here (http://www.filefactory.com/file/b4fd52e/n/GAMMA_TEST_CLIP_HD.mp4). You will find yourself adjusting many times for different sources until you settle for just a few presets. Or maybe you're lucky and you only have issues with that particular media. Btw, screenshots are not so useful as those do not reflect postprocessing. The best way to capture it is with a physical camera pointed at the screen.

Looks like panels these days are the same as light - not linear by design :cool: So most of us we have to live with less accuracy for deeper blacks without detail crush. Happy Backlit Bleeding, everyone :devil:

janos666
7th January 2011, 19:36
DirectX 10 and 11 can use the output from the processing format without changing it. The video card then uses the color LUT to convert the colors of the output frame and (preferably) input that at the highest acceptable bit depth format for the digital connection, or pass it trough a DAC to output analog signals. Such processing chains are completely normal for full-screen DirectX games with HDR

It sounds very interesting but I can't believe it. :p

I use my display with DisplayPort connection, so the output after the VGA LUT is always 10 bit/color RGB.

Do you say that I have real 10-bit display mode when I run any DX10/11 games with HDR rendering?
Can I really enjoy a real high dynamic range? Isn't it truncated/rounded or dithered back to 8-bit, and always 8-bit, every time in the current game engines?
(Did I miss the big marketing BS about the new features or did they forgot to diffuse BS around it?)

I didn't really played too much since I have this display and very few games use DX10+ (which I care about).

///Sidenote:
According to the HDMI-EDID info, it can receive 12 bit/color (not a surprise since the DeepColor standard requires at least 12 bit/color -> works in the practice or not is another question... ; There is no further information if it works with any resolutions or some resolutions which are smaller than the native resolutios.) But there is no any indicator which tells me the actual output bit depth when I use a HDMI connection. So, I am not sure if it's dithered 8-bit (ATI cards like to dither the output with single-link DVI connection too), real 10-bit, or what... That's why I kept the DP connection where I can see the indicator that it's real 10-bit. (Confirmed 10-bit <-vs-> "up-to-12bit but actually unknown")
What do you think about it?

And sorry for the offtopic talks, but: What do you think about the possibility to inject a small code into any DX engines which uses a 3DLUT for color correction (mostly for WCG displays)?
Would it be even possible? (I could see that a lot of thing can be done with a simple DLL injection.)

Last OFFtopic thing:
Aren't you interested in a small C++ practicing? :)
Here is this CMS engine: lcms2 (http://www.littlecms.com/). It's already used by MPC-HC to construct the "small" 3DLUT for color correction. (Another thing: Don't you want to increase the size of it? Like 256x256x256, for testing purposes...)
I think it would be very easy to write a small command line software which creates a madVR compatible 3DLUT (http://heanet.dl.sourceforge.net/project/thr3dlut/doc/specification.txt) with the necessary corrections between a reference (for example, a matrix+gamma type Rec709 virtual) and a device (display XYZ cLUT type) profiles.
But I have zero real life programming skills. (I gave it up after a short time during the basics of the object oriented programming and I kept learning civil engineering :p).

JanWillem32
8th January 2011, 06:02
Okay, a basic lesson in DirectX work then:
HDR allows the usage of complex shaders by allowing floating-point formats. I will keep the implication for the vertex math aside for now. In the past you had to be careful not to overstep 0% or 100% brightness for each of the 4 ARGB components, as integer formats such as A8R8G8B8 will always clamp the range to 0% or 100% for each step. Floating point surfaces have a sign bit that allow values below 0% and a number of exponent bits to allow values beyond 100%.
It's normal in games to have all kinds of layers of rendering by textures and shaders that set up a pixel before it's sent to the backbuffer. All those layers can overshoot the normal range, especially the lighting effects. Constantly clamping the range hurts the quality of black and white values. Additionally, HDR rendering often adjusts the dynamics of the contrast, brightness and gamma to human perception characteristics. Think about bloom effects, automatic adjustments to night vision, blinding effects by intense lights. The two floating-point color formats use 10 or 23 integer bits minimum in the normal range, for A16B16G16R16F or A32B32G32R32F formats respectably. That also helps to maintain more quality throughout the processing chain.
HDR techniques were introduced after the introduction of DirectX 9. DirectX 10 and 11 further refined them. Not all rendering engines use HDR techniques.

A real 10-bit display mode requires a complete display chain that maintains the quality throughout the chain. Currently, it's not possible to get better than 8-bit output to the video card without the fullscreen exclusive mode. The windows desktop locks the display mode to desktop format, that's a maximum of 8-bit with the current display drivers. The rendering engine of the program has to set the display mode to 10-bit or more, as well. DirectX 10 and 11 allow the complete rendered surface to be used as the display surface, even if it's in A32B32G32R32F. DirectX 9 is limited to these formats: http://msdn.microsoft.com/en-us/library/bb172558%28v=VS.85%29.aspx .

It's reported that 10- and 12-bit modes do work with both ATi and nVidia graphics cards. For digital signals, the receiver needs to set the capability of accepting the 10- and 12-bit modes. Single-link DVI doesn't have a lot of bandwidth, so that might be an obstacle, too.

The 3DLUT can be handled in the screenspace processing chain, just like the regular brightness and contrast settings. To make it work properly, it has to be compiled into the main engine.

I'm already developing a bit, and indeed I've taken a look at the CMS engine. It's one of the last items that's completely stuck to one format (A16B16G16R16F on the renderer side). I'd love to improve it, once I learn how it's operated.

@bobdynlan I do have to sort them a bit. I'm currently trying to get the shaders integrated into the main code, but it will need a bit of work to get there. I made too many shaders to handle in the current menu and the Y'CbCr-type shaders have to do RGB conversions because they are inserted in the wrong place in the processing chain.

janos666
8th January 2011, 14:15
You wrote a lot of things which I already knew or I don't feel important to answer my question. I hoped a simple Yes or No. :)


Currently, it's not possible to get better than 8-bit output to the video card without the fullscreen exclusive mode.

Is there a difference between the usual D3D Full Sreen Exclusive mode and how the usual D3D games work in Full Screen mode? (Do the games basically work in D3D Full Sreen Exclusive mode? Is there "Non-Exclusive D3D Full Screen" mode? Do games use that?)

The rendering engine of the program has to set the display mode to 10-bit or more, as well.

This is what never happens right now with any games, I think.

It's reported that 10- and 12-bit modes do work with both ATi and nVidia graphics cards.

MPC-HC uses it already, doesn't it?

DirectX 10 and 11 allow the complete rendered surface to be used as the display surface

I already quoted the period from your earlier post which puzzled me, but I think this period clarified it. It's allowed but that doesn't mean it's used.
You earlier post suggested (for me) that the final display output is automatically set to the highest available format with DX10+ engines. That's why I thought it means my current DX10+ games use 10 or even 12-bit output already.
But none of the current games (any DX or OpenGL game engines) work with more than 8 bit/color display output. Is this right?


That GUI looks nice. I hate the right-click menu.

JanWillem32
8th January 2011, 16:06
Is there a difference between the usual D3D Full Screen Exclusive mode and how the usual D3D games work in Full Screen mode? (Do the games basically work in D3D Full Screen Exclusive mode? Is there "Non-Exclusive D3D Full Screen" mode? Do games use that?)
There is a full screen "windowless" mode. It's like MPC-HC when you enable the "Full Screen" option in the right click menu. The exclusive mode performs a lot better. That's because there's no rendering or interference of the Windows desktop environment in the exclusive mode. A lot of games don't use exclusive mode, probably because it requires programmers with some DirectX or OpenGL skill.

This is what never happens right now with any games, I think.
It's indeed true that many games just do 8-bit output, often even with a complete 8-bit processing chain. That's because older video cards can't do anything else, IGP's lack capabilities, memory speed and processing power, and designing processing chains for low-end to high-end PCs is often too bothersome for programmers. At least MPC-HC allows switching the rendering modes.

MPC-HC uses it already, doesn't it?
8-bit regular or 10-bit in exclusive mode. DirectX 9 doesn't allow more than that. Video card drivers often constantly send signals to the display with the highest available color bit depth, to avoid losses when using the color LUT. That's even when the input format is of a lower bit depth.

I already quoted the period from your earlier post which puzzled me, but I think this period clarified it. It's allowed but that doesn't mean it's used.
You earlier post suggested (for me) that the final display output is automatically set to the highest available format with DX10+ engines. That's why I thought it means my current DX10+ games use 10 or even 12-bit output already.
But none of the current games (any DX or OpenGL game engines) work with more than 8 bit/color display output. Is this right?
I know a few developer demos that transfer between entire frontbuffers to be used as a backbuffer in DirectX 10/11. The surfaces, backbuffer and display format can be up to A32B32G32R32F. Such a mode allows the video card to execute dithering or rounding to the transferred format for DP/HDMI/DVI/analog. For games, well, see my other two comments.

That GUI looks nice. I hate the right-click menu.
Same for me, too. I'd love to have the option to set presets quickly in a menu, though.

JanWillem32
18th January 2011, 11:00
I've made some corrections to the "0-256 to 16-235 for SD&HD video output" and "16-235 to 0-256 for SD&HD video input" shaders.
There's also a new "unsharp luma mask for SD&HD video" for specific sharpening on luma.

cca
19th January 2011, 13:31
I've made some corrections to the "0-256 to 16-235 for SD&HD video output" and "16-235 to 0-256 for SD&HD video input" shaders.
There's also a new "unsharp luma mask for SD&HD video" for specific sharpening on luma.

http://www.mediafire.com/?n3skdfx0thvps53

Tried to download, instead mediafire gives "Error downloading file. Retrying..." and fails.

EDIT: the re-upload works, thank you.

JanWillem32
24th January 2011, 22:29
For this batch, I've cleaned up the gamma conversion shaders. I turns out that the video gamma transfer formula is simply never used. The usual gamma for consumer video mastering is 2.4. There are exceptions when 2.35 is used, and I've been told that some just transfer the Digital Cinema gamma of 2.6 (quite wrong for the current consumer devices).
I also added "semi-random colored surface noise" and "contour color".

mr.duck
5th February 2011, 04:45
I'm just using one of the shaders to adjust the saturation down a bit.

Most useful, thanks. Wish I found it sooner.

:thanks:

DottorLeo
6th February 2011, 03:02
JanWillem32 i'm experimenting your shader with MPC-HC, they works correctly, compile and stacks fine but there is a problem: the output video is all cutted around, all zoomed in as this picture (from Harry Potter and The Chamber of Secret DVD) instead of showing the entire upscaled picture:

http://img9.imageshack.us/img9/6632/cutji.th.png (http://img9.imageshack.us/i/cutji.png/)

I've disabled the internal scaler as you suggested some post before ("Scaling shaders require the "View", "Video Frame", "Normal Size" setting. This disables resolution scaling by the renderer, the picture is then centered on the screen with either black borders or parts of the frame cut off. ").

My monitor is a 16:10 LG that support up to 1080p resolution (Lg flatron e2250v). I have to specify the resolution manually in your shader somewhere?

Also i suggest you to copy your instruction from post #42 (http://forum.doom9.org/showpost.php?p=1457640&postcount=42) to the first one for better visibility.

ikarad
6th February 2011, 18:56
Where can I download mpc with these new shader because on xvidvideo.ru there aren't these shaders?

DottorLeo
6th February 2011, 21:05
Where can I download mpc with these new shader because on xvidvideo.ru there aren't these shaders?

You have to build them manually. Follow the #42 link on my last post. It's quite easy.

JanWillem32
6th February 2011, 23:10
The scaling shaders should be placed in the "Combine Screen Space Shaders..." window when up-scaling. I'm investigating why that item is currently grayed out for VMR-9. It's one of the last things we have to solve before starting to integrate some shaders.

JanWillem32
15th February 2011, 04:54
I added the "Pixel Shader Scripts, test 20.7z" file in my development folder, see my signature for the download. I'll try to edit the OP to something better, soon.
This is mostly cleanup and style formatting of the code. I did edit two shaders.
"contour color expose banding"
This shader is useful to visually expose even the slightest banding, but also encoded blocking and ringing artifacts. You can use this for example to test debanding and denoising filters.
"hue, saturation, luma gamma and chroma gamma control for SD&HD video input"
This shader is a nice update, it's now a lot more useful to influence over-saturated video trough chroma gamma control. I believe this function is rather unique. I've never seen it on any other software or hardware.
I came up with this idea after mr.duck's comment.

toniash
15th February 2011, 09:25
I added the "Pixel Shader Scripts, test 20.7z" file in my development folder, see my signature for the download. "hue, saturation, luma gamma and chroma gamma control for SD&HD video input"
This shader is a nice update, it's now a lot more useful to influence over-saturated video trough chroma gamma control. I believe this function is rather unique. I've never seen it on any other software or hardware.
I came up with this idea after mr.duck's comment.
Thanks for your good work!
It's possible to implement some visual controls so we can change the values and see the effect in realtime?

JanWillem32
15th February 2011, 16:50
Sure, but it will take some time, as that would require making a new items in the "options" screen. It's not possible to merge these with the "Color controls for VMR-9 (windowed)".

mr.duck
18th February 2011, 21:25
"hue, saturation, luma gamma and chroma gamma control for SD&HD video input"
This shader is a nice update, it's now a lot more useful to influence over-saturated video trough chroma gamma control. I believe this function is rather unique. I've never seen it on any other software or hardware.
I came up with this idea after mr.duck's comment.

I basically contributed nothing but some how feel like I helped :D

I'm using it now. It looks nice. I'm not sure on all the technical details I just tweaked chroma gamma till it looked good. Around 1.08 for me after 3 mins tweaking. Colors look natural. Flesh tones are the give-away.

I have a TN monitor. I set it to sRGB mode and can only adjust brightness and contrast. That's why this shader is so useful otherwise the video looks a bit garish. Would you say that adjusting chroma gamma is the best way of fixing it? Also why do some shaders such as the standard 16-235 -> 0-255 have [SD] and another for [SD][HD]? Does it really make any difference?

JanWillem32
19th February 2011, 00:03
I mostly updated that shader because even on my calibrated CRT some sources can be really over-saturated. Because the normal "saturation" setting damages the dynamic range, I thought it might be a nice update to implement the same gamma controls for luma and chroma as with the RGB controls. The chroma gamma setting preserves minimum and maximum saturation nicely, but can bend the s-shaped curves in the range <-.5,.5>, to get a lower or higher average saturation.

A TN monitor can be calibrated, I've done that with a dozen or so monitors and TV's. I own a X-Rite i1Display 2 to do calibration, but it did cost me € 183.
TN monitors have a difficult s-shaped RGB luminance versus voltage curve like all LCD screens, so those always need extensive editing to the analog voltage settings in the panel driver. It's too bad that many screens don't even nearly match any proper calibation at all (even the expensive ones). I've even seen the "dynamic" (torch) mode enabled by default.
I wonder if sRGB mode is a good choice in your case. I've never heard about a TN monitor that can display the full range of the sRGB spectrum anyway. A picture of the sRGB range and links to other ranges is available at http://en.wikipedia.org/wiki/SRGB .
On my monitor sRGB settings never worked well at all. After unlocking the "factory preset" menu and messing with all the settings, I've made a good calibration with the "6500K" setting. It could very well be that your monitor's sRGB setting isn't very accurate either. Apart from technical limitations, many screens (even cheap ones) can be calibrated a bit after unlocking service menus. There a quite a few guides on how to open it. Many service manuals for display devices can be found by a basic search. The service manual I use was hosted on quite a few websites. Maybe you can try that, too.

The 16-235 -> 0-255 SD shader was to fix an ATi driver problem in 2007 with SD sources. It was mentioned in the first few pages of this thread, along with some other things I wanted to point out. That shader is useless now, so that's why I didn't include it in my shader pack.

mr.duck
19th February 2011, 01:31
The default modes for the monitor was really horrendously bad. I don't know how much % of the sRGB spectrum the sRGB mode covers, but I guess it's the best the monitor is capable of. To me, it looks not just acceptable but pretty decent (for a TN anyway).

Sometimes I have seen some one else calibrate their monitor and post the result online for others with the same monitor to use. That would be good enough for me but I doubt anyone has bothered for this monitor. It's a BenQ G2420HDBL.

JanWillem32
19th February 2011, 02:19
The software part calibration (.ICC/.ICM file) only works with one hardware setting, and should be replaced monthly, due to aging components. (Quite a job if you do calibrations on a projector.) Just a warning not to use a downloaded one.
Your monitor is featured in quite an extensive thread on: http://forums.overclockers.co.uk/showthread.php?t=18089775&page=23 . Some people posted settings that seem to work for them. I haven't found a guide to enter factory/service mode. It's usually a menu that pops up with holding a button or two, while switching on with the "hard" on/off switch. I used to have a complete service manual, but this site shows how it's done for my monitor and it works on a lot of other monitors, as well: http://www.network54.com/Forum/87612/thread/1126720987/last-1126733323/HELP+Desperately+seeking+access+to+service+menu+Compaq+P1220+%28Mitsubishi+2060u%29 . Don't forget to note down settings, so you can always reset it. I've never seen a reset function in the service menus.

toniash
24th February 2011, 18:00
Sure, but it will take some time, as that would require making a new items in the "options" screen. It's not possible to merge these with the "Color controls for VMR-9 (windowed)".
I thought about some more generic with a standarized comment in front of the #define for each control from where to extract the min, max and default value and also a description and build a GUI with this values.

bobdynlan
25th February 2011, 01:23
I thought about some more generic with a standarized comment in front of the #define for each control from where to extract the min, max and default value and also a description and build a GUI with this values. Exactly what I'm working on - a limited meta parser, used in a "Live Shaders" gui bar, for easy adjusting of parameters with sliders. Will post a demo when I finish it.

toniash
25th February 2011, 11:11
Exactly what I'm working on - a limited meta parser, used in a "Live Shaders" gui bar, for easy adjusting of parameters with sliders. Will post a demo when I finish it.

PERFECT! thanks

JanWillem32
3rd March 2011, 07:20
A minor update to "semi-random colored surface noise" and some typo corrections were needed, so I've released the "Pixel Shader Scripts, test 21" package in my folder. No new functions were added this time.

toniash
10th March 2011, 15:49
@JanWillem32

in "unsharp luma mask for SD&HD video"
// minimum limit to sharpen, 0 means disabled, low = 8/16384., medium = 12/16384., high = 16/16384.
#define Threshold 12/4096.
What is wrong, the comment or the define?
Thanks

JanWillem32
10th March 2011, 16:11
I resolved major errors in "Catmull-Rom spline6 height resizer", "Catmull-Rom spline6 width resizer", "sharpen complex v2 + deband + denoise" and "sharpen complex v3 + deband + denoise".
I edited the comment in "unsharp luma mask for SD&HD video". Thank you toniash. The precursor to this shader was very sensitive to its input, the comment was a left-over.
Only the "blur" shaders are new.
Blur uses the same sampling area as "sharpen complex v3 + deband + denoise". In other words, it has the same debanding capacity.
Blur minor uses the same sampling area as "sharpen complex v2 + deband + denoise".
For "!readme - how to properly chain shaders" I added an optimization trick, mostly for screenspace shaders.

toniash
10th March 2011, 16:48
@JanWillem32

Couldn't be faster! :)

markanini
14th March 2011, 18:13
I'm excited about these scripts but I can't get my head around how to load them. Will any of these scripts be added to MPC-HC core?

Qaq
14th March 2011, 19:05
Open the shader editor by going to View > Shader Editor. In the title textbox at the top, enter the name of the shader, and select ps_3_0 from the drop down list on the right. Open shader file into a text editor, and copy and paste the contents into the shader editor. Close MPC. The shader will then be found under the Play > Shaders menu.

JanWillem32
28th March 2011, 19:51
For the latest pack I took some extra time to look up assembly math. It was pretty hard to improve my original shaders, but it was worth it. I made improvements to almost all shaders, and added a few new ones.
Color gates: These are a bit tricky to get working (the numerical intervals are narrow), but it's a popular filter, I've even seen this effect installed on an older smartphone (camera effect filter). It's an effect filter that allows an interval of colors to pass-trough unmodified, to highlight them and change the rest of the picture to grayscale.
Because the floating point surfaces behave differently compared to the integer types, it's sometimes necessary to make two different types of shaders for the same function.
To accommodate a common multi-pass function I added "optimized path for up-sampling floating point surfaces". It has 3 passes to up-sample a 4:2:0 source, and 2 passes to up-sample a 4:2:2 source. It's actually easy to merge multiple shaders that have only a single input in a single pass. To show how it's done, I also added all (optional) color control functions to step 3.

Deshi
29th March 2011, 08:45
Hi JanWillem32 !

I want to try your spline6 resizers with your "optimisation trick".
I mean, for height and width modifying as follow (for my 720p TV) :
float c1;
to
#define c1 (1/1280.)
float2 c1;
to
#define c1 float2(1/1280., 1/720.)
float c0;
to
#define c0 1280
float2 c0;
to
#define c0 float2(1280, 720)

But I was wondering about 2 things :
1) Do I have to modify the line : #define Magnify (4/3.) ?
2) If my input video is in 1080p, will it still works ? Because I would put these shaders in screen space.

Thanks

JanWillem32
29th March 2011, 09:48
1) Do I have to modify the line : #define Magnify (4/3.) ?Yes, the normal scalers get input numbers for the scaling and positioning and use custom surface sizes to work with. External shaders don't have that luxury.
2) If my input video is in 1080p, will it still works ? Because I would put these shaders in screen space.Another quote from those two shaders:
// This shader should be run as a screen space pixel shader if you are up-scaling.
// This shader should not be run as a screen space pixel shader if you are down-scaling.

I know, I really should get started to get 2-pass scaling working in the rendering engine. Additional scalers could have been integrated months ago if that item wasn't bugged.
Speaking of bugs, I messed up brightness, gamma and noise detection parameters for "sharpen complex v3 + deband + denoise" and "sharpen complex v2 + deband + denoise". These cause banding in low-light near-pure red, green or blue gradients. After some fine-tuning of those two I'll release another shader pack.

Deshi
29th March 2011, 10:44
Thanks for the quick reply !

So if I understand correctly I should put this :
#define Magnify (16/9.) with the fixed values for the "floats".

Does it mean that all video will be output in 16/9 and thus altering the aspect ratio ?

Does your last comment means that we should be able soon to choose in the renderer settings of MPC-HC the spline resizer instead of bicubic ?

One last for the road : :rolleyes:

Is there a benefit in putting deband + denoise before the resize is made ?

Thanks again.

JanWillem32
29th March 2011, 11:38
The correct item would be #define Magnify (2/3.) , as (1280/1920.) and (720/1080.) resolve to that fraction.
If I manage to get 2-pass scaling to work, I can probably get spline, Lanczos and other kinds of scalers integrated. The shader part is easy, but the (CPU-based) vertex setup of the 2-pass scalers is bad. It can't handle rotation at all and the current code uses incorrect math.
Sharpening kernels generally benefit from higher resolutions, but it depends on what you like. Just try some settings, but remember that most of the RGB-type shaders (including the default scalers) are written to be used on linear RGB input, so it's usually beneficial to include gamma conversion shaders in the filter chain.

Deshi
29th March 2011, 13:30
The correct item would be #define Magnify (2/3.) , as (1280/1920.) and (720/1080.) resolve to that fraction.
To be honnest I don't understand why I have to put (2/3.) if I get values to #define c1 (1/1280.), #define c1 float2(1/1280., 1/720.), #define c0 1280 and #define c0 float2(1280, 720).
But since I can't use the shader for both up/down-scaling it's not really an issue. For the down-scaling part it would be #define Magnify (3/2.), right ?
I've no idea how to get it in "shaders" or "screen space shaders" depending on resolution of the input...
Just for info : will it change the aspect ratio of the input ?

If I manage to get 2-pass scaling to work, I can probably get spline, Lanczos and other kinds of scalers integrated. The shader part is easy, but the (CPU-based) vertex setup of the 2-pass scalers is bad. It can't handle rotation at all and the current code uses incorrect math.
Knowing that the work is in progress is still a good news :cool:
If you solve this, does it mean that the included renderer of MPC will be able to perform as MadVR ?
In an utopic setting, will it be possible to have a renderer in which you can choose/set options like resizer, sharpen, denoise, deband, deringing... ?

Sharpening kernels generally benefit from higher resolutions, but it depends on what you like. Just try some settings, but remember that most of the RGB-type shaders (including the default scalers) are written to be used on linear RGB input, so it's usually beneficial to include gamma conversion shaders in the filter chain.
The conversion of gamma was implied, but in my question I was deliberatly refering only to deband + denoise. Setting in the shader all the values of sharpening to 0.
But then, is there a benefit to use the sharpen + deband + denoise in screen space ? Before re-converting to video RGB of course...

JanWillem32
29th March 2011, 16:22
To be honnest I don't understand why I have to put (2/3.) if I get values to #define c1 (1/1280.), #define c1 float2(1/1280., 1/720.), #define c0 1280 and #define c0 float2(1280, 720).The original frame is 1920×1080 and it's scaled to 1280×720, that's a factor 2/3 in both dimensions.
#define c1 (1/1280.), #define c1 float2(1/1280., 1/720.), #define c0 1280 and #define c0 float2(1280, 720) only work in screenspace. For down-scaling I advise to use the default registrations of c0 and c1. That's because a lot of 1080p source material isn't 1920×1080 at all. I have videos that use 1440×1080 and 1920×800, for example.
But since I can't use the shader for both up/down-scaling it's not really an issue. For the down-scaling part it would be #define Magnify (3/2.), right ?(2/3.)I've no idea how to get it in "shaders" or "screen space shaders" depending on resolution of the input...I use .REG files to switch profiles (only works if the program isn't running). It's a manual method, but it's a lot faster than setting up shaders in the combine menus.
An example, for setting a preset of some shaders in both video resolution space and screenspace:Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Gabest\Media Player Classic\Shaders]
"Combine"="RGBtYCC|CRS5Ch420|CRS5Ch422|sc10a1.5"
"CombineScreenSpace"="CRS6h1080|CRS6w1080"
"Initialized"=dword:00000001

[HKEY_CURRENT_USER\Software\Gabest\Media Player Classic\Settings]
"ShaderListScreenSpace"="CRS6h1080|CRS6w1080|"
"Shaders List"="RGBtYCC|CRS5Ch420|CRS5Ch422|sc10a1.5|"
"ToggleShader"=dword:00000000
"ToggleShaderScreenSpace"=dword:00000000(Yes, even I don't use those huge names for the shaders internally.)Just for info : will it change the aspect ratio of the input ?That only happens when the magnification factor for the height and width shader are different.Knowing that the work is in progress is still a good news :cool:
If you solve this, does it mean that the included renderer of MPC will be able to perform as MadVR ?
In an utopic setting, will it be possible to have a renderer in which you can choose/set options like resizer, sharpen, denoise, deband, deringing... ?I'll just try to work my magic in the limited amount of time I have. I'd love to work on a lot of things, but as I'm the only developer currently working on the video renderers, it's pretty hard to get everything done. We simply lack developers that can write C++, do some management in the bug tracker, maintain this forum section or be available on the IRC channel. Integrating some shaders to work like the final pass shader (color management+dithering) would be very nice, but it takes a lot of time to develop that kind of systems.The conversion of gamma was implied, but in my question I was deliberatly refering only to deband + denoise. Setting in the shader all the values of sharpening to 0.
But then, is there a benefit to use the sharpen + deband + denoise in screen space ? Before re-converting to video RGB of course...The higher the resolution you place the filter in, the lower the chance of aliasing becomes, but it also adds to the risk of blurring some low-contrast details that are already blurred by up-scaling. Higher resolutions use relatively more processing power than lower ones.
Filtering in the lowest of the two resolutions will often blur less details, with the exception of fine checkerboard patterns and similar things (those just scale badly).
The "sharpen complex v3 + deband + denoise" and "sharpen complex v2 + deband + denoise" shaders can blur a lot if EdgeSharpen (detection limit) is disabled. Be careful with that parameter. The sharpen parameters should cause only very minor blurring when set to 0. Good luck in finding the settings you like.

For Pixel Shader Scripts, test 24, I updated the "sharpen complex v3 + deband + denoise" and "sharpen complex v2 + deband + denoise" shaders. They now work properly again. I also added "optimized path for up-sampling chroma on integer surfaces" and cleaned up a bit of code.

CruNcher
29th March 2011, 17:07
JanWillem32 im not so into after XP Media architecture but especially for Vista/7 wouldn't be utilizing DirectCompute be much more powerfull and also allow more flexibility for the Players Post Processing (Scaling) (lower cpu overhead, less PCI-E transfer overhead) theoreticaly lower power consumption :) ?

so for the most efficiency wouldn't it be better to utilize 2 different paths

Windows XP = Shader via VMR9 Renderless (Directx 9 on GPUs supported most Nvidia/ATI/Intel)
Vista/7/8 = Direct Compute Shader (any renderer ?) (Directx 10/11 Newer GPU generation starting already with G92 for Nvidia, even earlier for AMD/ATI)

I didn't benchmarked Vista/7 Video efficiency yet compared to XP but according to Microsoft they improved quite a lot in Rendering efficiency, im still happy with XP performance though :)

It seems their are no real Benchmarks of the Media Part differences existing and comparing vs XP either with Aero or without (and DWM entirely disabled)

Though seeing that Intel for example is only going exclusive in their Media SDK 2.0 with Vista/7 is a little frightening (no official XP support anymore, though they are the only ones might be also a try to push their Hollywood approved DRM ecosystem faster on as many Systems as possible, users need to change to Vista/7 to utilize it and their Partners 1080p services)


"Specifically, DirectCompute technology helps accelerate the performance across several scenarios that historically took a long time to complete when just using the CPU. CyberLink's support of DirectCompute in their latest applications results in higher performance across these scenarios - something that our joint customers have asked for."

I guess Arcsoft utilizes it already for their Sim3D and SimHD on Windows XP they do it knowingly with either CUDA/OPENCL(mainly for ATI compatibility)/CPU same as Cyberlink does for their Truetheater PP or Corel/Intervideo for WinDVD

JanWillem32
31st March 2011, 21:34
I like DirectCompute too, but for graphics with synchronization for the threads it requires a DirectX 11 video card and a supported OS. DirectX 10 hardware can still use DirectCompute in offline mode, but I don't know if a DirectCompute shader on Directx 10 hardware can be modified to render images.
In the future, many developers hope to indeed be able to set up a full rendering engine to be managed by the GPU. Rendering paths currently use the CPU at every step of drawing operations to set up the GPU and start rendering objects, while the input and output objects themselves are nearly always loaded in the video memory and cache.
I saw this article a few days ago, it seems that the manufacturers are ready to move to low-level control: http://www.bit-tech.net/hardware/graphics/2011/03/16/farewell-to-directx/ .

For more efficiency in any custom renderer, it would be best to drop the VMR-9 and EVR mixers and use a custom mixer (even for the DirectX 9 platform). A renderer written in DirectX 11 that's written to use level 4.0 instructions will also work on DirectX 10 and 10.1 hardware.
I would most certainly like to help writing a DirectX 11 renderer, but only once a custom mixer is done and the EVR CP-sync merge is completed (both are long overdue). That's going to require some more C++ developers. If anyone's interested to write code or manage communication for the project, they're most welcome.

Vista's WMP features EVR. If you compare that to the previous VMR-9 (windowed) renderer, it's indeed a big improvement, but it's still inferior to the quality provided in custom renderers,

Aero is a nice GUI renderer, it's not really that heavy on the CPU, GPU and the two kinds of RAM. The only problems I have with it are the forceful synchronization method in windowed mode (sometimes even in exclusive mode) that can cause tearing.

I don't know anything about Intel's Media SDK 2.0, but I do know that Intel never provided support for their GPU's DXVA on Windows systems older than Vista, so I'm not that surprised.

I'd definitely like to look at the code by Arcsoft. It's a lot of work to write and maintain code for three types of APIs. I've also never written anything with CUDA or OPENCL.

I fixed some things in the colorfulness gamma processing for the color control shaders. no new functions were added this time.

CruNcher
1st April 2011, 16:59
I like DirectCompute too, but for graphics with synchronization for the threads it requires a DirectX 11 video card and a supported OS. DirectX 10 hardware can still use DirectCompute in offline mode, but I don't know if a DirectCompute shader on Directx 10 hardware can be modified to render images.
In the future, many developers hope to indeed be able to set up a full rendering engine to be managed by the GPU. Rendering paths currently use the CPU at every step of drawing operations to set up the GPU and start rendering objects, while the input and output objects themselves are nearly always loaded in the video memory and cache.
I saw this article a few days ago, it seems that the manufacturers are ready to move to low-level control: http://www.bit-tech.net/hardware/graphics/2011/03/16/farewell-to-directx/ .

For more efficiency in any custom renderer, it would be best to drop the VMR-9 and EVR mixers and use a custom mixer (even for the DirectX 9 platform). A renderer written in DirectX 11 that's written to use level 4.0 instructions will also work on DirectX 10 and 10.1 hardware.
I would most certainly like to help writing a DirectX 11 renderer, but only once a custom mixer is done and the EVR CP-sync merge is completed (both are long overdue). That's going to require some more C++ developers. If anyone's interested to write code or manage communication for the project, they're most welcome.

Vista's WMP features EVR. If you compare that to the previous VMR-9 (windowed) renderer, it's indeed a big improvement, but it's still inferior to the quality provided in custom renderers,

Aero is a nice GUI renderer, it's not really that heavy on the CPU, GPU and the two kinds of RAM. The only problems I have with it are the forceful synchronization method in windowed mode (sometimes even in exclusive mode) that can cause tearing.

I don't know anything about Intel's Media SDK 2.0, but I do know that Intel never provided support for their GPU's DXVA on Windows systems older than Vista, so I'm not that surprised.

I'd definitely like to look at the code by Arcsoft. It's a lot of work to write and maintain code for three types of APIs. I've also never written anything with CUDA or OPENCL.

I fixed some things in the colorfulness gamma processing for the color control shaders. no new functions were added this time.
direct link: http://www.mediafire.com/?azp7ak75uy2u8z9

Yep i see what Huddy said was indeed starting a lot of discussions over on beyond3d but most see it as a step back from clean APIs to oldshool direct hardware coding, and surely Microsoft wont let this happen and many Devs also don't really want it too ;)
The Rendering Architect of the Frostbite 2.0 Engine even took it into his GDC presentation http://publications.dice.se/attachments/GDC11_DX11inBF3_Public.pdf ;)

About the Aero (DWM) thing i saw this though i couldn't confirm this myself and it might be FUD but it seems plausible if their are really these functions missing in WDDM 1.1 i wonder if it was added back into WDDM 2.0 though ?

http://www.youtube.com/watch?v=ToFgYylqP_U
http://www.youtube.com/watch?v=ay-gqx18UTM

When WDDM 2.0 was announced back in 2006 @ WinHec it sounded really good but we still not their http://forum.beyond3d.com/showthread.php?t=59068

http://download.microsoft.com/download/5/b/9/5b97017b-e28a-4bae-ba48-174cf47d23cd/pri103_wh06.ppt <- WinHEC 2006 presentation.

I tried todo some experiment on Win XP capturing the Windows screen (via bitblit function which is slow on XP and said to be faster on Vista/7 due to going through Direct3D) and Encoding it on the GPU and comparing that to a CPU Framework i could save some energy so far but the frame drops on Direct3D 9 are heavy the CPU overhead is still to heavy (trying to capturing game content but with mixed GPU/CPU Kernel, preparing GPU kernel only test) and unmanaged a pain (Video capturing works quiet well especially if its accelerated).

Though under XP and VMR9 i experience another Playback problem currently and im not sure where it comes from i suspect Windows High Resolution Kernel timing and Decoder that doesn't support it but im not entirely sure http://forum.doom9.org/showpost.php?p=1488882&postcount=144 Cyberlink guys seem todo it quiete different then other ISVs http://forum.doom9.org/showpost.php?p=1488268.

JanWillem32
2nd April 2011, 04:57
The sheets from that presentation are quite informative for people that can already develop for a DirectX-driven engine. I lacks the full presentation text or whitepaper, so it's not completely clear on all points for me. I did see that they are aiming for the level 5.0 instructions. I would be careful with that, as it will not work with DirectX 10 (level 4.0) and 10.1 (level 4.1) hardware at all. DirectX 11 hardware is still a bit rare in the general mid-to-high-end section of the market they are aiming for.
I still hope it will be possible to insert execution-level assembly code in the GPU as a processor unit in the future. Inserting execution-level assembly code without an API or driver translation has been possible for CPU's since they were first created (some assembly :p of the CISC to RISC elements required with the ancient x86+extensions instruction set).
For the parts with dependent-level instructions on the GPU (the typical vertex and pixel shaders), the assembly code is already nearly directly injected into the GPU, so those parts are really efficient already.

I don't know much about WDDM, as I've never worked on fundamental GUI elements. It becomes a lot less of an obstacle in exclusive mode, of course too. I'll probably have to gain some experience with it to get windowed mode applications I'm working on to work properly.

Bitblit functions are slow in general for operations on the backbuffers, no matter the DirectX version (or OpenGL for that matter). It's much faster to make a screenspace copy of the last item in the actual render chain. The penalty is that if you incur an anti-aliasing filter or more items in the transfer step to a back-buffer, your screenshot of a rendered image will not have those filters.
Video capturing is also heavy because of the encoding load. Anyone that has done capturing, mastering and editing on high-quality digital video content (not the 8-bit consumer-grade junk), will acknowledge that converting more than a terabyte of raw images to JPEG2000 on even a good RAID storage system will take like forever. The 8-bit consumer-grade junk is heavy to encode in real-time conditions too, of course. Since most consumers and professionals lack the storage capacity and sufficient writing speed on the medium to write out raw images, it's often required to write out encoded video. Unless you use a dedicated external encoding solution, there will always be a big performance hit for capturing with a video codec active on the same processor.

When it comes to timing, I hope to finally get rid of the EVR and VMR mixers for the common renderer in MPC-HC. Neither will signal the allocator correctly about the timings, so a lot of correction is required to make both work (for convenience, I omit the cases with badly encoded video and the VC-1 timestamps problem in MPEG transport streams).
Maybe if developers come along, willing to help with the mixer and renderers in general, the project can finally improve in quality and performance. There has already been talk about changing the font rendering engine for usage in the subtitle, OSD and stats screen rendering. I hope we can gather enough resources and people to get that done.

burfadel
2nd April 2011, 07:57
@Janwillem32

The shader v25 are great. The optimised path for up-sampling chroma on floating point surfaces works very nicely. The previous version I was using v23? had issues, so its great that is been resolved! I must admit, I have gone off the sharpen complex + deband + denoise filters, to me, it seems they are only ideal on almost perfect sources (using light denoise). Not just perfect encodes of ordinary sources!

I'm now using the optimised path for floating point surfaces, then the unsharp filter, which gives a nice result across all sources (not just across HQ source and encoding like the sharpen complex filters), and I add the greyscale noise right at the end. Its a very nice randomisation of the greyscale noise.

On the point of the greyscale filter, I found the strength a little high, I had to change it back to around 2 from 7 to look good on the tv. For me, the ideal amount of noise is just a little as it appears at viewing distance. It does a good job of hiding banding, whilst bringing out other details and making the picture actually look sharper! Is it possible to have the deband shader by itself, instead of combined with the sharpen and denoise filter? I do realise if you do use the noise shader it has to be placed after the sharpen/deband/denoise shader!

The worst thing about all these shaders is putting them into mpc-hc, you have to triple check to make sure all of them has been entered correctly, and can't modify the shaders unless a video is playing (which is very silly IMO).

Anyways, thanks for the great work, its very much appreciated!

Edit:
I should point out that I do like the concept of the sharpen+deband+denoise filter, it but for me, like suggested in the info, it did seem to pick the banding up more, and on some dark scenes it did oversharpen some noise which of course made it look not so good. Of course, a heavier denoise filter helps, but that could possibly remove some picture detail.

I think on high bitrate, 10 bit encodes of good quality digital sources, this filter chain would work really well (light denoise only).

I should also point out that even for normal material, its a shader that seems to work well or not on a per video basis!

The floating point optimised chroma upsample, then unsharp (I upped the strength slightly), then greyscale noise (I reduced the strength as said previous) works well with all material I tested it with. On a tv show I had recorded from HDTV, I've had two other people comment on why it looked so much better on my TV then it did on their new LED HDTV's (watched live, + replay from their own recordings). The funny thing about this is, the TV is A Toshiba CRT HDTV (the fact its CRT I think helps), but since it doesn't have a HDMI output I have been using the Svideo input - 1024x768! I must admit the picture quality even with SDTV stuff looks amazing on this TV. Further to their astonishment, I had already encoded it to X264 CRF 18, and reduced the resolution to just below SDTV. I used FFDSHOW to resize the output to 1024x768/

I would like to know how to use the resize filters (I believe they're really resampling filters?), in terms of designating a fixed output size. Having fixed output sizes such as 1024x768, 1680x1050, 1920x1080 etc for screen sizes, I think would be quite beneficial, as I have no idea how to use them currently! if the aspect ratio comes out wrong, maybe setting the aspect override in MPC should correct for it...?

JanWillem32
2nd April 2011, 09:59
Thank you, burfadel. I've also noted that the "sharpen complex + deband + denoise"-type shaders are indeed sensitive to the input they get. A lot of the general color controls affect the normal debanding capacity a lot, and like many shaders, they are meant for linear RGB.
// This shader benefits from converting to linear RGB, instead of using video gamma input directly.
Maybe I have to write a better description for that. It just means that this type of shader expects linear RGB by means of pre-processing by one of the two "gamma conversion of video RGB to linear RGB"-type shaders and post-processing by the color management function on the linear input setting, or one of the two "gamma conversion of linear RGB to video RGB"-type shaders.
Using a filter for linear inputs is quite common, it's used often in Photoshop and many other renderers use it, too. The bilinear and bicubic scalers in MPC-HC assume a linear input, as well.

The recent builds I've been posting on the main thread have a modified version of "semi-random colored surface noise" as an option for the dithering. It features contour detection, to exclude source areas that are already noisy, and the quantized noise ranges from 3 to 31 levels (generally lower than the standard noise shaders). The "sharpen complex + deband + denoise"-type shaders are detail detection shaders for multiple levels in multiple directions. The processing load from executing the blur and sharpen filters is very little compared to this detection they use. The sharpen filters can be disabled (instructions are included what numbers to set), but they can be a bit blurry without the balancing of the sharpening parts. Just try some settings, and test to get the image processing you want.

I don't like how the shaders are switched, either. VMR-9 (renderless) even has a bug that disallows access to the screenspace shaders menu. The easiest way to set shaders without having to start a video, is currently by using .REG profiles. It might also be better if shaders could be loaded from a "shaders" folder, instead of a .INI file or the registry. That would make inserting and removing a lot easier. I'll have to look if I can make that possible.

The resizers are prototypes for integration. I currently use the spline6 types, as you can see in the .REG example of post #209. I made a few presets with different scaling and noise filtering amounts. The scalers are actually quite simple: disable all internal scaling of MPC-HC, set a fixed scaling amount for the horizontal and vertical dimensions and scale the picture. The amounts are completely fixed, so I have to use different ones for all input resolutions. If I would be bothered to change the output resolution, I would have to make a completely new set of shaders and registry presets for that resolution, too.

Deshi
6th April 2011, 16:01
@burfadel

Hi, I'm trying to understand your chain of shaders but since I'm not so good in english...
Do you use Y'CbCr instead of RGB shaders simply because of your CRT output ?

So your chain looks like that :
Shaders,
- 1. RGB to Y'CbCr for SD&HD video input for floating point surfaces (in the optimized folder)
- 2. special 4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling (in the optimized folder)
- 3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling and color controls (in the optimized folder)
- unsharp luma mask for SD&HD video (higher settings)
Screenspace Shaders :
- sharpen + deband + mild denoise (sharpen at 0 ?)
- semi-random grayscale noise (lower settings)

Am I right ? Hopefully... :rolleyes:

burfadel
6th April 2011, 16:26
I'm not so sure about the Y'CbCr, JanWillem32 might be able to answer that better for you! I'm actually outputting from the graphics card as s-video, so 1024x768. I disabled mpc-hc's internal h264 DXVA and ffmpeg decoders, as well as the Xvid decoder and using ffdshow instead. I use the deband filter in ffdshow, with strength of around 1.8, and the radius at the default 16, as well as ffdshow's post-processing filter. I use the ffdshow resizer set to 1024x768, using spline resizer for both luma and chroma, and have some luma sharpening and a little chroma gaussian blur+sharpen when resizing.

For the semi-random greyscale noise I actually had to decrease the strength as 7 ended up with a very noisy picture, I have it set at around 2 instead. The semi-random greyscale noise shouldn't be run as a screenspace shader either, according to the comments in the shader file.

My shader chain:
- 1. RGB to Y'CbCr for SD&HD video input for floating point surfaces (in the optimized folder)
- 2. special 4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling (in the optimized folder)
- 3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling and color controls (in the optimized folder)
- 16-235 to 0-256 for SD&HD video input
- unsharp luma mask for SD&HD video (higher settings)
- semi-random grayscale noise (lower settings)

The 16-235 to 0-256 for SD&HD video input is highlighted because I was told it shouldn't be needed! however, for me anyway, the picture does look better both on the computer and tv with it :)

JanWillem32
7th April 2011, 00:25
@Deshi: Y'CbCr, xyY and other luma-chroma systems are just another way of encoding visibly representable colors. They can always be transformed back and forth to the R'G'B' values by matrices. The matrix and the following gamma correction to linear RGB depends on the specification of the input image. The choice of calculating in a luma-chroma, R'G'B' or linear RGB system depends on the filter's transformation type. With the exception of "0-256 to 16-235 for SD&HD video output" (memo: needs proper naming), color controls, color management and dithering, all filters will only depend on the specification of the input image. It's perfectly normal to have filtering with luma-chroma, R'G'B' and linear RGB systems in a single processing chain.

@burfadel: The "16-235 to 0-256 for SD&HD video input" shader is a correction shader for if the mixer fails (very rare). On normal video it breaks the white point, because of the chroma transformation. That's generally very undesirable. If the white point should be adapted, it should be done in linear RGB space with "brightness, contrast and gamma control for RGB", or more conveniently, with the color controls provided in "3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling and color controls".
The other point is dynamics: that shader removes 13% of the normal intervals. That's a lot of clipping in the white and black ranges. If for example a night scene is encoded at the bottom [0, .125] R'G'B' interval (quite normal), this shader chain will crush half of the bottom brightness range in that scene to black.
The usual method of changing color controls, is done by using grayscale gamma and colorfulness gamma to balance the picture.
If that doesn't work out, try colorfulness gamma, hue, saturation and the three RGB gamma controls instead.
Lastly, if that's not enough, try the colorfulness gamma, hue, saturation and the nine RGB gamma, brightness and contrast controls instead. The brightness and contrast controls will damage dynamic ranges (black and white crushing) and will change the white point if the values for red, green and blue are not the same.
At least with this method you have direct control on what kind of color transformations are performed.

Deshi
7th April 2011, 15:31
@burfadel & @JanWillem32

Thanks for the answers

@JanWillem32

What are the differences between floating point surfaces and integer surfaces ?

JanWillem32
7th April 2011, 21:11
What are the differences between floating point surfaces and integer surfaces ?DirectX 9 specifies a lot of different formats for projecting colors on a surface: http://msdn.microsoft.com/en-us/library/bb172558%28v=VS.85%29.aspx . It's basically a setting that allows the output of 32-bit floating point math of RGBA colors to be rounded and stored into memory or a file format. Note that old GPUs may have 16- or 24-bit internal processing pipelines, but even low-budget video cards have been internally 32-bit for years now.
Currently available formats in MPC-HC for the surface, backbuffer and display modes: X8R8G8B8/A8R8G8B8 and A2R10G10B10.
X8R8G8B8/A8R8G8B8 is the 8-bit RGB mode, 24 integer bits are used for RGB, 8 bits are discarded. (The subtitle and OSD screen do use the alpha transparency channel of A8R8G8B8 to make overlays over the main video.)
A2R10G10B10 is the 10-bit mode, 30 integer bits are used for RGB, 2 bits are discarded. It requires enabling the 10-bit RGB Output mode to activate it on the surface and backbuffer. Setting 10-bit output on the display mode requires Windows 7 or Server 2008 R2 and activation of the D3D Fullscreen Mode.
A16B16G16R16F and A32B32G32R32F are floating point surfaces, activated by Half Floating Point Processing and Full Floating Point Processing, respectively. These modes will override 10-bit output mode on the working surfaces mode, but not on the backbuffer and display mode.
Normal range RGB color data has an interval of [0, 1]. The integer types will scale to that range by dividing the integer data in the 8- and 10-bit formats by 255 or 1023, respectively. That's called quantization. The floating point formats can store data in that interval natively, because of the available exponent bits.
For the floating point formats (in correct order for the IEEE floating point data format);
3 sign bits are used to allow RGB values to be negative, this modifies a format's interval to [-1, 1];
30 or 69 integer bits are used for most of the normal range RGB data;
15 or 24 bits are used for exponent data to scale the integer values to very small binary fractions, such as i/4096 or to very large ones, such as i*8192, this modifies the format's interval to [-∞, ∞];
16 or 32 bits are discarded.
A basic overview of the technical data on floating point specifications: http://en.wikipedia.org/wiki/IEEE_754-2008 .

The reason why I have to write different shaders for integer and floating point formats, is mainly because of the sign bit. The signed values allow the normal Y'CbCr intervals to be used: [0, 1], [-.5, .5] and [-.5, .5]. Integer surfaces require an offset of .5 to compensate for that.
Another issue is exponentiation by even values on negative values. For example: .25² = -.25² = .0625 . For color data with negative values, it's undesirable to become positive like that, so compensation code to keep negative values negative is required for it.

Fluffbutt
11th April 2011, 16:08
Just out of interest, do the shaders in MPC_HC not work in the x64 version?

Mine are switched off, and the options to turn them on a greyed out and untouchable.

G_M_C
12th April 2011, 07:50
@ Fluffbutt: Did you try other renderer. EVR-CP is the one I use, and it all works for me.

@JanWillem32: I only want to use you shaders for up-sampling chroma. I use full fp processing and i use 10 bit output.

In 'combine shaders' i have set '4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input' followed by '4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input'.
But now i read you have 'optimized shaders' for chroma up-sampling. Should i use those ?

My question: Most things we watch are x264 encoded / 4:2:0 video. As i only want to use your shaders for up-sampling chroma an use full fp processing and use 10 bit output to try to get the best colors (image) i can get on my setup. Could write down for how i can achichieve what i want, and how /what shaders to use ?

Fluffbutt
12th April 2011, 09:28
G_M_C !!!!

Thanks you!!

It works perfectly - the last time I tried EVR-CP (on 7 x32 install) it complained about missing entries in about 3 dll files (evr.dll, or one)

I didn't think to try it on the new install of 7 x64 because of that.

<I bow to your erudition>

G_M_C
13th April 2011, 16:24
@JanWillem32: I only want to use you shaders for up-sampling chroma. I use full fp processing and i use 10 bit output.

In 'combine shaders' i have set '4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input' followed by '4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input'.
But now i read you have 'optimized shaders' for chroma up-sampling. Should i use those ?

My question: Most things we watch are x264 encoded / 4:2:0 video. As i only want to use your shaders for up-sampling chroma an use full fp processing and use 10 bit output to try to get the best colors (image) i can get on my setup. Could write down for how i can achichieve what i want, and how /what shaders to use ?

Did you fall of the WWW Janwillem ?
;)

JanWillem32
16th April 2011, 13:56
Sorry I didn't respond earlier.
Anyway, for both x86 and x64: EVR CP, EVR Sync and VMR-9 (renderless) have shader support. VMR-9 (renderless) needs to have a bug fixed for the grayed out screen space shaders item. Also, I'd like the shader menus to work in offline mode, instead of only during rendering.

@G_M_C: The optimized path uses a set of 3 shaders to up-sample 4:2:0 input (1, 2 and 3) or two shaders to up-sample 4:2:2 input (1 and 3). Just chain the shaders as the very first items. The last shader also features full color controls and a linear gamma output option. For the rest, it's up to you. There are a lot of possible shader chains, and what people like to render with them is all very different.
Renderer settings I use:
D3D Full Screen Mode, 10-bit RGB Output, Full Floating Point Processing, Disable desktop composition (Aero), Flush GPU after Present
(No VSync is required on a CRT in D3D Full Screen Mode, my projector does need VSync, but it features native 24/1.001 and 24 Hz modes to make it a lot easier.)

Shader chain:
1. RGB to Y'CbCr for SD&HD video input for floating point surfaces
2. special 4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input
3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input (linear output enabled, sometimes I also set colorfulness gamma to lower a high colorfulness on some video sources)
sharpen complex, deband and denoise, r=5 (denoise filtering strength dependent on the source)

Screenspace shaders: (I hope I can integrate some new scalers soon...)
Catmull-Rom spline6 height resizer (with correct scaling preset)
Catmull-Rom spline6 width resizer (with correct scaling preset)
final pass: color management with an ICC profile installed system-wide and random ordered dithering


I've re-written the sharpen complex, deband and denoise combination, and I'm going to rename it to something more correct. There's one dilemma: the type of composing code for the detection method has two good candidates, dot and length. I'd like users to try out what they like most, so I included both types. Both types are about equally heavy in processing, have relatively about the same amount of sharpening, have the same controls for the parameters, are now more gamma-corrected than their predecessors and have correct math.
To directly see the difference between the dot and the length methods, I've included modified RGB grayscale shaders, featuring both methods. Linear gamma conversion shaders are also included, as all these shaders require linear RGB input.
Please tell me what you see, what I can improve, and what you like or dislike about these shaders. I'll update the main shader package with some bug fixes and new items soon.

G_M_C
21st April 2011, 10:25
Sorry I didn't respond earlier.
Anyway, for both x86 and x64: EVR CP, EVR Sync and VMR-9 (renderless) have shader support. VMR-9 (renderless) needs to have a bug fixed for the grayed out screen space shaders item. Also, I'd like the shader menus to work in offline mode, instead of only during rendering.

@G_M_C: The optimized path uses a set of 3 shaders to up-sample 4:2:0 input (1, 2 and 3) or two shaders to up-sample 4:2:2 input (1 and 3). Just chain the shaders as the very first items. The last shader also features full color controls and a linear gamma output option. For the rest, it's up to you. There are a lot of possible shader chains, and what people like to render with them is all very different.
Renderer settings I use:
D3D Full Screen Mode, 10-bit RGB Output, Full Floating Point Processing, Disable desktop composition (Aero), Flush GPU after Present
(No VSync is required on a CRT in D3D Full Screen Mode, my projector does need VSync, but it features native 24/1.001 and 24 Hz modes to make it a lot easier.)

Shader chain:
1. RGB to Y'CbCr for SD&HD video input for floating point surfaces
2. special 4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input
3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input (linear output enabled, sometimes I also set colorfulness gamma to lower a high colorfulness on some video sources)
sharpen complex, deband and denoise, r=5 (denoise filtering strength dependent on the source)

Screenspace shaders: (I hope I can integrate some new scalers soon...)
Catmull-Rom spline6 height resizer (with correct scaling preset)
Catmull-Rom spline6 width resizer (with correct scaling preset)
final pass: color management with an ICC profile installed system-wide and random ordered dithering


I've re-written the sharpen complex, deband and denoise combination, and I'm going to rename it to something more correct. There's one dilemma: the type of composing code for the detection method has two good candidates, dot and length. I'd like users to try out what they like most, so I included both types. Both types are about equally heavy in processing, have relatively about the same amount of sharpening, have the same controls for the parameters, are now more gamma-corrected than their predecessors and have correct math.
To directly see the difference between the dot and the length methods, I've included modified RGB grayscale shaders, featuring both methods. Linear gamma conversion shaders are also included, as all these shaders require linear RGB input.
Please tell me what you see, what I can improve, and what you like or dislike about these shaders. I'll update the main shader package with some bug fixes and new items soon.
direct link: http://www.mediafire.com/?wouof3og84n97va

Thx for the tips JanWillem; I've been running the upsampling shaders 1-2-3 for a short while now, and it seems to work perfectly. GPU usages seems to be significantly lower (25~30 with 1080p on my HD5770, which switches to 400 GPU/900 Mem when running the shaders) with these three, as opposed to the 'regular'/non-optimized shaders.

JanWillem32
25th May 2011, 17:50
After a few final touches, I've packed the v1.0 of Video pixel shader pack.
Compared to the previous version, I've updated all shaders. A lot of bugfixes, optimizations and a few new filter types were added. See the new opening post of this thread for reference.

For "sharpen complex, deband and denoise" I've been trying to get gamma+brightness correction sorted out. Especially small gradients with patterns are difficult to blur and sharpen. A dark scene makes that even more difficult.
I've been using a video gamma to linear factor of 2.6 to compensate a bit for that (the normal shader uses 2.4). Near-black source banding is unfortunately very common (and inevitable with current standards) in consumer-grade video. Bending the gamma curve to a higher value does make the picture generally quite dark in most videos, but is in my case quite effective for keeping darker scenes with about the same quality as lighter ones.
I haven't found settings/filters yet that can really work with a lower gamma (2.2 to 2.4), without using a synthetic video input in the renderer (those simply don't have the source banding problem). I still need to work on that.

G_M_C
26th May 2011, 20:16
Jan, i want to report this:
I'm using R25 of your optimized shaders for chroma upsampling on floating point surfaces. I have a HD5770 running on Win7-64. I use MPC-HT 32 bit, your test version R2964 (where ctrl-j still worked as it should).

When i enable RGB colorcontrols (#define RGBColorControls 1) and set blue brightness slightly higher (#define BlueBrightness 0.1) I get a fully blue screen, like BlueBrighness was defined @ 10 in stead of 0.1.

Jan-Willem; This problem remains still with V1.00

JanWillem32
26th May 2011, 22:45
That could be something hardware-specific, as I can't replicate it. I'll make a few variants that use other assembly structures to test.
Try for example:
s1.b += BlueBrightness;
instead of the complete line that processes contrast and brightness for RGB.

Video pixel shader pack v1.1 changelog:
"brightness, contrast and gamma control for RGB": corrected brightness calculation.
"cubic B-spline6 width resizer" and "cubic B-spline6 height resizer": corrected naming for variables.

G_M_C
30th May 2011, 17:21
Jan-Willem; Have not found time to test the changes, sorry.

Will do testing as soon as i can, using newest drivers/version of your test-builds etc.

Roco
17th June 2011, 15:29
JanWillem32,
I'm trying to write a shader for MPC-HC, is it possible to take two different parts of the screen (e.g the first-third and the third-third at x axis) and put them side by side to compose a new frame, or a tile? Alternatively, can you point me to where can I ask this question? Or, is there a relative example?

JanWillem32
17th June 2011, 16:45
That one's not so hard. Note that this shader will only use point sampling/nearest neighbor to move the parts around. Sub-pixel interpolation for scaling and moving items requires adding code for interpolation. If you want to construct something like the sphere or wave shaders, point sampling just won't look good.sampler s0;

float4 main(float2 tex : TEXCOORD0) : COLOR
{
return (tex.x < 1/6. || tex.x > 5/6.)? float4(0, 0, 0, 1)// black borders
: tex2D(s0, tex+float2((tex.x > .5)? 1/6. : -1/6., 0));// slide 1/3. horizontal parts inward
}

Roco
18th June 2011, 11:12
JanWillem32, thank you very much! :)
I asked this question to understand by-example the fundamentals without bothering you, but although this is 100% clear and I've learned a lot, I'm having a hard time to extend this to moving an arbitrary part of the screen to a desired position using both x & y axis. I currently don't need borders, but it was very useful to know how -thanks!

I just want to arrange parts of the original frame to compose a new frame which will be smaller, so this final composition would be scaled to cover the whole frame. I'm working on it and although I have some progress, it's more difficult than I thought -it's like trying to solve an ancient mind puzzle with minimum input data! I know I should be reading books instead -and I usually do, lots of them, but spending a month to study 1000 things in order to use just 1, is not very efficient, especially when there is no spare time left.

I don't want to mess up with your thread, but if you can provide me just a hint about how to take 3 arbitrary parts (x, y) and put them into arbitrary positions (x, y) to build a new borderless frame, it would be of great help -I'd greatly appreciate it.



EDIT: Movement at pixel units is all I need in my case. About scaling, I might have to think about interpolation next, thanks!

JanWillem32
18th June 2011, 12:57
Don't worry about a messy thread. I'm fine with this, as long as it draws some attention.
Randomization code is expensive, but the two noise effect shaders have examples of how to implement it, if you really need it.
Ordered switching is a lot less expensive. A nice example of that is the random ordered dithering code. With a bit of editing, you can also use that method on other textures, too:// (C) 2011 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// flip and rotate sampling direction for RGB
// This shader can be run as a screen space pixel shader.
// This shader requires compiling with ps_2_0, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// If possible, avoid compiling with the software emulation modes (ps_?_sw). Pixel shaders require a lot of processing power to run in real-time software mode.
// This shader will flip and rotate the red, green and blue components individually every 32 frames.
// Note that this shader is only accurate in rotating squares.

sampler s0;
float3 c0;

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float ct = frac(c0.z/256.+.0625);// 8-state counter

float2 rs, gs, bs, txi = tex.yx;
if(ct < .125) {rs = tex*float2(-1, 1); gs = txi*float2(-1, 1); bs = tex*-1;}
else if(ct < .25) {rs = txi*float2(1, -1); gs = txi*-1; bs = tex;}
else if(ct < .375) {rs = tex*float2(1, -1); gs = txi; bs = tex*float2(-1, 1);}
else if(ct < .5) {rs = txi*float2(-1, 1); gs = tex*-1; bs = txi*float2(1, -1);}
else if(ct < .625) {rs = txi*-1; gs = tex; bs = tex*float2(1, -1);}
else if(ct < .75) {rs = txi; gs = tex*float2(-1, 1); bs = txi*float2(-1, 1);}
else if(ct < .875) {rs = tex*-1; gs = txi*float2(1, -1); bs = txi*-1;}
else {rs = tex; gs = tex*float2(1, -1); bs = txi;}

return float4(tex2D(s0, frac(rs)).r, tex2D(s0, frac(gs)).g, tex2D(s0, frac(bs)).ba);// sample RGB positions and output
}It takes a while before you get used to programming for SIMD vectors. Playing with the basic tex.xy, tex.yx, and the 1-x or 1-y variants is a nice start. Note that if you set U and V sampler states on the input to mirror mode, you can remove the frac() parts for the sampling position. The same with the c0 register: 3 out of 4 numbers aren't used in this case.

Roco
19th June 2011, 14:39
Good example JanWillem32,
with your two posts and a little experimentation, I finally managed to have results! :)
Thank you very much!

JanWillem32
19th June 2011, 20:07
You're very welcome. If you need any more code examples or optimization, please tell me. If you've finished something, I can also include a commented and copyrighted version of the code in a next release.

Qaq
23rd June 2011, 17:19
JanWillem32, I'm trying to figure out the best way to fix that "Fellowship Of The Ring" green tint:
http://www.nerdsociety.com/unboxing-lotr-ee-bluray-green-tint-issue/
Is it hard to make a special shader for green color correction? And thanks for your work.

JanWillem32
23rd June 2011, 17:55
I don't think a hue or saturation shift is useful for this problem ("brightness, contrast, grayscale gamma, colorfulness gamma, hue and saturation control for SD&HD video input").
For "brightness, contrast and gamma control for RGB" the green controls are all separate. "GreenGamma" would be the first to experiment with, as this one doesn't affect the dynamic range. If that's not enough, you can try Brightness and Contrast settings.
Because the optimized forms of the 4:2:2 chroma up-sampling shader were easy to combine with all color controls, they are also available in those shaders.

JanWillem32
6th July 2011, 07:32
I've added and fixed a few things, so I'm releasing a new version.

log:
added "3LCD panel software alignment, Catmull-Rom spline6 interpolated" shaders
added "r=6, sharpen complex, deband and denoise" and "r=6 blur" shaders
corrected "sharpen complex, deband and denoise" shaders for bad performance during texture sampling stages and a clipping artifacts problem on very sharp contours
added "flip and rotate sampling direction for RGB"

mindbomb
8th July 2011, 05:06
im getting artifacts when using chroma blur, usually they happen horizontally across the bottom of the screen.

im wondering if im using it right, do you just copy and paste the text into the shader editor?

im using a 4350, windows 7, mpc hc 1.5.2.3329 (sse2), cat 11.6

edit: i think my hardware was just crappin out on me, i overclocked the card and now it is fine.

JanWillem32
8th July 2011, 06:19
GPU-Z is usually a good tool to log statistics of the GPU for diagnostics. If GPU usage hits 100% usage, frames start to drop, and if temperatures are high, the chances of getting artifacts become bigger.

mindbomb
8th July 2011, 07:13
it seems to drop frames when it gets to around 85% actually. idk, maybe im bandwidth limited or something.

JanWillem32
8th July 2011, 07:39
It's probably the memory bus and memory speed. Many low-end cards have enough memory, but lack the ability to really fill it. A HD4350 only has a 64-bit memory bus and usually DDR2 memory.

alph@
8th July 2011, 18:37
i have tried your version of mpc (1.5.2.3329), why the image is so sharp, with the internal mpc decoder (ffmpeg) H264.
http://www.zimagez.com/miniature/jahn.png (http://www.zimagez.com/zimage/jahn.php)

mpc jannwillem (h264 ffmpeg)interne.

http://www.zimagez.com/miniature/pot57.png (http://www.zimagez.com/zimage/pot57.php)

potplayer-diavc-ffdshow(just resize)

JanWillem32
8th July 2011, 19:36
Well, that looks like EVR CP with default settings in the ATi CCC video tab: http://forum.doom9.org/showthread.php?p=1512344#post1512344 (what a coincidence).
First, let's try to set those filters to something you like. Next, you'll probably would want to enable the "Touch Window From Inside" and "Keep Aspect Ratio" settings under "View", "Video Frame" to correct scaling a bit.
That should clean things up quite a bit.
After that, you can try out the new scalers under the "View", "Options", "Output" tab. (There are only a few options right now, but I'll add more later on.) For pixel shaders, don't forget the chroma up-sampling shaders. On the ATi platform there's no chroma up-sampling without them if you enable 10-bit RGB output or full or halt floating point processing.
Depending on what filters you enable, you can make the picture in MPC-HC look like the bottom one, or whatever you like. To stay a bit impartial, all regular pixel shaders in the pack should work fine in PotPlayer, too.

alph@
8th July 2011, 20:23
yes you are right, the edge ehancement is active (45),this is the first time I see work :),I already disable the other filters (noise, deblocking ....)for the ratio and the output level, do not worry,everything is ok to be display on my lcd sony 46 hx 700,I do not use shaders with potplayer because I use madvr,I use your shader with tokplayer,It's very convenient to use, a dialog box with the shaders, the change is instantaneous,an can be done when the player is in 'pause'.
http://www.zimagez.com/miniature/tok0.png (http://www.zimagez.com/zimage/tok0.php)
shader selection in tokplayer

the chroma up-sampling shaders is necessary, I do not see too much difference?
thanks.

JanWillem32
8th July 2011, 20:56
The chroma up-sampling shaders only work on point sampled chroma in the renderer. It's something that the shaders I wrote can take advantage of when a different color format than X8R8G8B8 is used on ATi hardware. (10-bit RGB output or full or half floating point processing modes change surfaces to A2R10G10B10, A32B32G32R32F and A16B16G16R16F respectively.) The default chroma up-sampling by the display drivers is only a bilinear kernel, so I've been trying to disable it universally and allow the user to also select other filters instead (with little success yet, unfortunately).

G_M_C
8th July 2011, 21:17
The chroma up-sampling shaders only work on point sampled chroma in the renderer. It's something that the shaders I wrote can take advantage of when a different color format than X8R8G8B8 is used on ATi hardware. (10-bit RGB output or full or half floating point processing modes change surfaces to A2R10G10B10, A32B32G32R32F and A16B16G16R16F respectively.) The default chroma up-sampling by the display drivers is only a bilinear kernel, so I've been trying to disable it universally and allow the user to also select other filters instead (with little success yet, unfortunately).

probably offtopic;


ITC processing is a feature that enables display processors to use the appropriate pixel data processing algorithms based on specific content type to ensure video quality.
With ITC processing, the graphics driver enables the display to use its own video quality processing algorithms for movies played in full-screen mode on HDMI™ displays.
[...]
Select—Enables ITC processing for HDMI displays that are capable of the feature. When movies are played in full-screen mode, the display’s processors can be used to ensure video quality.
Clear—Disables ITC processing. Video quality is ensured by the graphics driver for all types of contents displayed.


I wonder, when reading this: Does enabling ITC processing on Ati disable the interferance of CCC ? And does it force the GPU to just output data as-is, and leaving processing up to an external processor ?

JanWillem32
8th July 2011, 22:03
Chroma up-sampling is a required feature of any video player. There's no possibility of setting something else than full range 4:4:4 RGB on the back buffer. On top of that, transmission trough the video ports limits the output accuracy (that's why the output should be dithered). The signal is only good enough to go straight to the display panel(s) without any further digital processing at all. (And even then, I really hate being limited to 8-bit and 10-bit outputs. Projection systems with 12-bit panels and better have been around for a bit more than a decade now.)
If the external processor has access to the source file and handles decoding, rendering, color management, dithering and the execution stages to the display's analog controls with equal or better DCI compliant studio formats, I'd be willing to use it. Else, it's just another obstruction that the software rendering stages can do much better.
http://forum.doom9.org/showthread.php?p=1507282#post1507282It's already difficult for software developers to get along with the internal hardware of PCs (drivers, interaction with other software, CPU/GPU performance and so on). External hardware is at a whole other level. I believe that the CRT TV my parents bought in 1994 behaved a lot better then most of the current TVs in the same price class today. Although it was limited to D-SUB and lesser analog connections, it behaved quite similar to a monitor after geometry adjustment.

TheElix
8th July 2011, 22:14
Projection systems with 12-bit panels and better have been around for a bit more than a decade now.)12-bit output on projectors?! For real?

JanWillem32
8th July 2011, 22:51
DCI demands it as a minimum. The demands for processing are even higher. In terms of DirectX 9 color formats, only A16B16G16R16 (non float) and A32B32G32R32F would suffice for processing from beginning to end.
My projector is 12-bit, too. I only wish I had a more absolute control on it (to disable more stuff). It's not that bad if I compare it to some other display devices, though. It exposes the full gamut in full range RGB mode, and allows almost full user control over all the internal parts in the OSD. I just don't like the post-processing part.

TheElix
8th July 2011, 23:41
From the times I've seen projectors I can't say I found their images more colourful or contrasty than PDPs, for example.

JanWillem32
9th July 2011, 01:04
Aside from those in labs and specialist environments, the digital (and even analog ones, in some ways) projectors in cinemas aren't bad at all. I'm talking about types that generally weigh more than 100 kg, of course.

Eliminateur
22nd July 2011, 00:43
Jan, i'm not clear on what is a screen space shader and what is not.
latest MPC buils have only 2 shader types: "pre resize" and "post resize".
so what do i use where?, could you update the readme?

i'm having the infamous red on black pixelating issue with ati and dxva and i'm trying to solve it with your pack.
which of the shaders should i use?, i'm using FFPP so i guess i'll use the ones for FP surfaces but i have no idea which of the 3 to use.
i used 2 and 3 and i get green and white converted to purple!

i also have a wide gamut display so i tried to use "gamma conversion of linear RGB to wide gamut RGB for floating point surfaces" as post-resize and it didn't change... anything....

fairchild
22nd July 2011, 00:56
I asked something similair in the other thread. When using the YV12 Chroma upsampling shader, does it have to be done on pre or post resize and/or on both? I'd imagine some of the chroma shaders in this pack is similair.

Eliminateur
22nd July 2011, 01:35
hmm i had to use 1->2->3 compiled for PS3 and now it works.

one more thing, creating new shaders in mpchc is a CHORE, you can select a "blank one" so you need to change the name, press enter, then delete everything in the window THEN copypaste, then enter in the name again so it gets compiled, etc etc.
shader editor is quite crappy as it is

JanWillem32
22nd July 2011, 01:47
The "post resize" item used to be "screenspace". The skipping chroma isn't specific to DXVA, but to enabling either HFPP, FFPP, or 10-bit RGB output on ATi hardware.
Your situation could use this basic setup:
Shader chain:
1. RGB to Y'CbCr for SD&HD video input for floating point surfaces
2. special 4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input
3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input (linear output enabled)

Post resize shaders:
gamma conversion of linear RGB to video RGB for floating point surfaces

I linearize the gamma to avoid darkening artifacts on R'G'B' color blending. Here's an example of no gamma correction throughout the filter stages: http://photocreations.ca/interpolator/index.html .
Of course, you can also edit all kinds of color controls in the step 3 shader, and add a few custom shaders.
The last shader can simply be edited to any display gamma. The common range is usually from 1/2.2 to 1/2.6 . The 256/563. and 5/12. values are just two presets. The linearization power in step 3 is 2.4.
For lighter processing, you can enable the single-pass bilinear filter instead of steps 1, 2 and 3.
A video file encoded with 4:2:2 chroma down-sampling doesn't need step 2.

I'll take a look at adding a full list of chroma interpolation shaders later, I've finished quite a few resizers, anyway. The idea of making the shader collection external to the player in .TXT files was rejected. Shaders will have to be loaded from the registry or from a .INI file (warning: the .INI file can only store small ones).
You can copy from the registry if you need a backup or portability: http://forum.doom9.org/showthread.php?p=1514362#post1514362 .

Eliminateur
22nd July 2011, 04:04
hmmm this is werid i'm having problems with the 1-2-3 shaders.
when i tested before, it worked ok, now i keep seeing pixelation on red, and activating/deactivating/recompiling is not doing anything.
if i open shader editor and i ente the name it says "could not load shader", is that the problem of the .ini file?
how big is "small ones"?

Also, i was using the 16-235 -> 0-255 [SD][HD] to correct levels, after using your 1-2-3 shaders it doesn't works anymore, even if i put it in pre/post/before/after
i really like that shader because without it, blacks are "grey" in my monitor(hmm but if i enable that shader i lose black details as they go very black).

anyway, the linearization shader makes the gamma go extremely high, i've tried with 5/12 and it's still too bright, settled with 451/563 for now -i'm gonna do much more trial and error-, it brightens it up a little without ruining the blacks much.

btw, all this is valid for DXVA that outputs NV12, but when i use soft decoding i'm outputting RGB32 from ffdshow, how will these shaders act in that case?

oh, about processing power, compiled everything with PS3.0, tried playing back a moderate 1080p clip w/DXVA and all shaders active, GPU usage hovering 48%(with UVD clocks) so i have aaaample processing power to spare

JanWillem32
22nd July 2011, 08:23
"Small ones", as in: the total may not exceed 15 KB, I believe. The Windows registry has a limitation in size of 1 MB per entry.

For "16-235 -> 0-255 [SD][HD]", see page one of this thread and a few onwards. It's one of the shaders I'm definitely going to delete. It has also been several years since the last report of a driver/mixer that makes this flaw, as well.
Gray tints in video where you normally expect darker tints is normally caused by a low display gamma. Try your hand at a tool that can help set up your monitor controls. Note that most of those tools set up for a gamma of 2.2, consumer-grade video is a bit steeper normally at around 2.4.

The "gamma conversion of linear RGB to video RGB for floating point surfaces" shader de-linearizes the gamma from step 3 (activated manually in the shader). You shouldn't need to set it to a value far beyond the normal interval of 1/2.2 to 1/2.6 .
For any normal color controls, you can also activate controls for Y'CbCr and RGB stages in step 3. Those are meant to correct specific flaws in an encoded video, not so much the flaws in a display.

RGB32 is a compatibility option for usage with older video cards that can't really deal with any video processing at all. It's not a default output normally. Unless you are viewing a .BMP file through the Windows still image filter, you should never get RGB32/X8R8G8B8 as input for the mixer. Valid input for the mixer with 8-bit 4:2:0 Y'CbCr video files is NV12 or YV12, with 8-bit 4:2:2 Y'CbCr video files is YUY2.

I'm familiar with having headroom in processing power. I set my HD4890 at 700/975 clocks during video playback. It only has momentary spikes over 90% GPU usage now and then on 1080p video, even with my heavy rendering chain. (I do need set the full 3D clocks of 850/975 for a 1080i sample I have, though.) It has a nasty habit of setting the clocks to 500/975 in combination with DXVA playback, which is too low for my needs on 1080p, so that's why I override them.

CiNcH
24th July 2011, 14:35
Hi Jan,

I am currently also fooling around with pixel shaders and have a little problem...

I am creating a pixel shader:

D3DXCompileShaderFromFile( buffer, NULL, NULL, "main", "ps_2_a",dwShaderFlags, &pCode,&pBufferErrors, &g_pConstantTablePS[i] );
g_pd3dDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(),&g_pPixelShader);


I then draw the quad:

g_pd3dDevice->SetVertexShader(NULL);
g_pd3dDevice->SetPixelShader(g_pPixelShader);
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
g_pd3dDevice->SetPixelShader(NULL);


This works like a charm.

I then switch pixel shader version to 3.0:

D3DXCompileShaderFromFile( buffer, NULL, NULL, "main", "ps_3.0",dwShaderFlags, &pCode,&pBufferErrors, &g_pConstantTablePS[i] );


When I do this, the quad is not drawn. I only see the background color which has been set with the call to g_pd3dDevice->Clear.

Do you have any idea what is going wrong when setting pixel shader version to 3.0?

(I am loading D3DX9_43.dll BTW)

Eliminateur
24th July 2011, 16:31
i use rgb32 because i want maximum quality output without any mixer or driver doing anything to the color conversion(i don't trust them) and i find ffdshow software HQ conversion is much better than the mixer.

i've been toying with the shaders more, and with RGB32 input they actually lower the quality of the chroma, it's like it downscales it(starts blurring and pixellating the red on black borders)

about the gamm, i tried your setting and it was so high it was unwatchable(i'm going to post screenshots later.
I've tried monitor setting wizard in the past, they all result in values that i don't like how they apper, either too dark or too bright i'm using custom TGB with close to 100 value, brightness at 4 and contrast 40)

"Small ones", as in: the total may not exceed 15 KB, I believe. The Windows registry has a limitation in size of 1 MB per entry.

For "16-235 -> 0-255 [SD][HD]", see page one of this thread and a few onwards. It's one of the shaders I'm definitely going to delete. It has also been several years since the last report of a driver/mixer that makes this flaw, as well.
Gray tints in video where you normally expect darker tints is normally caused by a low display gamma. Try your hand at a tool that can help set up your monitor controls. Note that most of those tools set up for a gamma of 2.2, consumer-grade video is a bit steeper normally at around 2.4.

The "gamma conversion of linear RGB to video RGB for floating point surfaces" shader de-linearizes the gamma from step 3 (activated manually in the shader). You shouldn't need to set it to a value far beyond the normal interval of 1/2.2 to 1/2.6 .
For any normal color controls, you can also activate controls for Y'CbCr and RGB stages in step 3. Those are meant to correct specific flaws in an encoded video, not so much the flaws in a display.

RGB32 is a compatibility option for usage with older video cards that can't really deal with any video processing at all. It's not a default output normally. Unless you are viewing a .BMP file through the Windows still image filter, you should never get RGB32/X8R8G8B8 as input for the mixer. Valid input for the mixer with 8-bit 4:2:0 Y'CbCr video files is NV12 or YV12, with 8-bit 4:2:2 Y'CbCr video files is YUY2.

I'm familiar with having headroom in processing power. I set my HD4890 at 700/975 clocks during video playback. It only has momentary spikes over 90% GPU usage now and then on 1080p video, even with my heavy rendering chain. (I do need set the full 3D clocks of 850/975 for a 1080i sample I have, though.) It has a nasty habit of setting the clocks to 500/975 in combination with DXVA playback, which is too low for my needs on 1080p, so that's why I override them.

Eliminateur
25th July 2011, 01:59
i've uploaded the screens to dropbox to maintain them in PNG as jpg masked the errors, the filename shows the settings used
http://dl.dropbox.com/u/3493496/screens.zip

here's what i can conclude from them in parts:

1st part - no shaders
DXVA chroma looks horribly blocky as expected
soft(ffdshow w/RGB32 HQ output) and DXVA 8bit looks almost the same(differences in contrast/brightness due to CCC video improvements and also because ffdshow uses deband filter).
Verdict: i prefer the brighter looking DXVA 8bit output, soft looks more blurred

2nd part - with shaders(using the 3 shaders in the chroma interpolation folder for floating surfaces):
DXVA 10b looks almost the same as 8bit with no shaders(since save image does not capture post-shader output i had to printscreen the file)
soft decoding shows blocky chroma with shaders
Verdict: again, soft looks blurred and dxva 8b w/out shaders looks exactly the same as with chroma shaders.

what's the point of going the extra 10b route if i can go to 8b and not use any shader?

for the gamma conversion screen, again the screen capture does not get the shader output so i had to capture with printscreen, you can see how horrible it looks with default 256/563 value

JanWillem32
25th July 2011, 15:48
@CiNcH: To test: manually change "ps_3.0" to "ps_3_0".
For a more advanced solution:
Header file: typedef LPCSTR (WINAPI* D3DXGetPixelShaderProfilePtr)(LPDIRECT3DDEVICE9 pDevice);
typedef HRESULT (WINAPI* D3DXCompileShaderPtr)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
typedef HRESULT (WINAPI* D3DXDisassembleShaderPtr)(CONST DWORD* pShader, bool EnableColorCode, LPCSTR pComments, LPD3DXBUFFER* ppDisassembly);

D3DXGetPixelShaderProfilePtr m_pD3DXGetPixelShaderProfile;
D3DXCompileShaderPtr m_pD3DXCompileShader;
D3DXDisassembleShaderPtr m_pD3DXDisassembleShader;Initialization section: const HINSTANCE hDll = recent version of D3DX9Dll;
if(hDll) {
m_pD3DXCompileShader = reinterpret_cast<D3DXCompileShaderPtr>(GetProcAddress(hDll, "D3DXCompileShader"));
m_pD3DXDisassembleShader = reinterpret_cast<D3DXDisassembleShaderPtr>(GetProcAddress(hDll, "D3DXDisassembleShader"));
m_pD3DXGetPixelShaderProfile = reinterpret_cast<D3DXGetPixelShaderProfilePtr>(GetProcAddress(hDll, "D3DXGetPixelShaderProfile"));}
...
m_pProfile = m_pD3DXGetPixelShaderProfile(m_pD3DDev);// get the pixel shader profile levelm_pProfile is a LPCSTR you can use as a direct input for "LPCSTR pProfile" input of m_pD3DXCompileShader, it should be renewed every time a device is re-made or reset.
The other two should behave properly after initialization like this.

It's possible to write a shader that has a very poor ordering system, so that it does compile on level 2.x, but not on level 3.0. It's possible to disable flow control for those.
For the command-line interface for the standalone compiler it's the /Gfa switch. (The compiler is fxc.exe in the "x86" and "x64" folders of "Microsoft DirectX SDK (June 2010)\Utilities\bin\" .)

For the other parts: DrawIndexedPrimitive can be more efficient, avoid "g_pd3dDevice->somecall(NULL);" as much as possible, as it doesn't come for free.

@Eliminateur: I've verified the color transfer matrices to be accurate up to quite a few bits for both VMR-9 and EVR. For the main set of matrices, see: http://msdn.microsoft.com/en-us/library/ms698715%28v=vs.85%29.aspx . (The bt.601 and bt.709 matrices are also used for the two xvYCC types.)
The driver only performs abnormal filtering because filters are set in the CCC in your case. I suggest everyone to manually set up the filters in the video options tab of the video card's driver suite. ATi, Intel and nVidia all implement the filters as optional, but some are enabled by default. Those filters do cost processing power, and may also not be to your liking, either.
Using X8R8G8B8 (RGB32) when 8-bit RGB isn't the source format is pretty destructive; Y'CbCr/xvYCC sources lose the data from the [0, 15] and [236, 255], [241, 255], [241, 255] intervals (8-bit quantization assumed). That doesn't happen with the mixer working on A32B32G32R32F (FFPP) or A16B16G16R16F (HFPP) surfaces. As those names imply, the mixer quantization is quite a bit better with those two formats, too.

For providing gamma correction for internal filtering stages (includes the internal resizers) after chroma up-sampling and color conversion, I added the "LinearRGBOutput" switch to step 3. It's made to linearize the encoding gamma of 1/2.4 to 1, so no darkening artifacts occur with the internal filtering stages when blending colors. To avoid some complaints, I've not enabled the function by default.

CiNcH
25th July 2011, 16:29
Thanks for your answer.

@CiNcH: To test: manually change "ps_3.0" to "ps_3_0".
Copy/paste mistake, sorry. I of course set it to ps_3_0.

I am already feeding the output of 'D3DXGetPixelShaderProfile' into 'D3DXCompileShader', which is ps_3_0.

Still ps_3_0 profile does not work for some reason. Within MPC-HC it does.

JanWillem32
25th July 2011, 16:37
Does fxc.exe generate any warnings or errors (even in strict mode)? It's rather rare that all ps 3.0 items would fail.
I assume that hardware vertex processing is enabled?

CiNcH
25th July 2011, 17:08
Yes, 'hardware vertex processing' is enabled. I use the very simple greyscale shader for testing purpose.

CiNcH
25th July 2011, 17:30
May this be due to the fact that i use fixed-function transforms like SetTransform?

JanWillem32
25th July 2011, 18:33
SetTransform probably isn't a big problem, although a static index and vertex buffer in video usually gains a few % of performance for resolving vertices. I don't think I've ever used pre-defined transforms yet, except for world view input data to vertex shaders.header:
#pragma pack(push, 1)// this directive is used on MYD3DVERTEX to copy 32-bit aligned vertex data to video memory on x86 and x64
template<unsigned texcoords>
struct MYD3DVERTEX {
float x, y, z, rhw; struct {
float u, v;} t[texcoords];};
template<>
struct MYD3DVERTEX<0ui32> {
float x, y, z, rhw; DWORD Diffuse;};
#pragma pack(pop)

CComPtr<IDirect3DIndexBuffer9> m_pIBuffer;
CComPtr<IDirect3DVertexBuffer9> m_pVBuffer;


main:
if(!m_pIBuffer) {
// prepare the static index buffer in video RAM
static const short indices[6] = {0, 1, 2, 2, 1, 3};// two triangles
void* pVoid;// void pointer for memcpy
// create an index buffer interface
hr = m_pD3DDev->CreateIndexBuffer(sizeof(indices), D3DUSAGE_DONOTCLIP|D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIBuffer, NULL);
// lock m_pIBuffer and load the indices into it
hr = m_pIBuffer->Lock(0, 0, reinterpret_cast<void**>(&pVoid), D3DLOCK_NOSYSLOCK);
memcpy(pVoid, indices, sizeof(indices));
hr = m_pIBuffer->Unlock();
// set the static index buffer
hr = m_pD3DDev->SetIndices(m_pIBuffer);}

m_pD3DDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_TEX1);

...
Although unfinished, the current AlphaBlt code can serve as a nice example.

HRESULT CDX9RenderingEngine::AlphaBlt(IDirect3DTexture9* pSubtitleTexture, const CRect rcSubSrc, const CRect rcSubDest)
{// only used by DX9AllocatorPresenter.cpp to blend subtitles with resizing
// TODO: add resizing shaders
HRESULT hr;

static CRect Scrsrc, Scrdst;
if(Scrsrc != rcSubSrc || Scrdst != rcSubDest || !m_pAlphaBltVBuffer) {
m_pAlphaBltVBuffer = NULL;
Scrsrc = rcSubSrc;
Scrdst = rcSubDest;
D3DSURFACE_DESC d3dsd = {D3DFMT_UNKNOWN, D3DRTYPE_SURFACE, 0, D3DPOOL_DEFAULT, D3DMULTISAMPLE_NONE, 0, 0, 0};
if(FAILED(hr = pSubtitleTexture->GetLevelDesc(0, &d3dsd))) return hr;

const float wrp = 1.0f/static_cast<float>(d3dsd.Width), hrp = 1.0f/static_cast<float>(d3dsd.Height),
rsl = static_cast<float>(rcSubSrc.left)*wrp, rsr = static_cast<float>(rcSubSrc.right)*wrp, rst = static_cast<float>(rcSubSrc.top)*hrp, rsb = static_cast<float>(rcSubSrc.bottom)*hrp,
rdl = static_cast<float>(rcSubDest.left)-0.5f, rdr = static_cast<float>(rcSubDest.right)-0.5f, rdt = static_cast<float>(rcSubDest.top)-0.5f, rdb = static_cast<float>(rcSubDest.bottom)-0.5f;
const MYD3DVERTEX<1> v[4] = {
{rdl, rdt, 0.5f, 2.0f, rsl, rst},
{rdr, rdt, 0.5f, 2.0f, rsr, rst},
{rdl, rdb, 0.5f, 2.0f, rsl, rsb},
{rdr, rdb, 0.5f, 2.0f, rsr, rsb}};

// prepare the vertex buffer in video RAM
void* pVoid;// void pointer for memcpy
// create a vertex buffer interface
hr = m_pD3DDev->CreateVertexBuffer(sizeof(v), D3DUSAGE_DONOTCLIP|D3DUSAGE_WRITEONLY, D3DFVF_XYZRHW|D3DFVF_TEX1, D3DPOOL_DEFAULT, &m_pAlphaBltVBuffer, NULL);
// lock m_pVBuffer and load the vertices into it
hr = m_pAlphaBltVBuffer->Lock(0, 0, reinterpret_cast<void**>(&pVoid), D3DLOCK_NOSYSLOCK);
memcpy(pVoid, v, sizeof(v));
hr = m_pAlphaBltVBuffer->Unlock();}

// set the special vertex buffer
m_pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
m_pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
hr = m_pD3DDev->SetStreamSource(0, m_pAlphaBltVBuffer, 0, sizeof(MYD3DVERTEX<1>));

// draw the rectangle
hr = m_pD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);

// cleanup: set the normal vertex buffer
hr = m_pD3DDev->SetStreamSource(0, m_pVBuffer, 0, sizeof(MYD3DVERTEX<1>));
m_pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
m_pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
return hr;
}

CiNcH
25th July 2011, 19:18
I have no idea anymore what could be wrong :( .

CiNcH
25th July 2011, 19:44
I now found this (http://www.gamedev.net/topic/489553-how-to-replace-setfvf-with-vertex-shader/page__view__findpost__p__4196329). I am using

D3DFVF_XYZ or D3DFVF_DIFFUSE or D3DFVF_TEX1

and not

D3DFVF_XYZRHW

JanWillem32
26th July 2011, 00:07
Interesting that it even worked on 2.x levels.
D3DFVF_DIFFUSE needs a color as a masked ABGR in the vertex data statement, D3DFVF_TEX1 would map a texture on top of that color. I guess it has some use with some kinds of alpha blending, material layering or lighting, but those things are more for end-stage design.
D3DFVF_XYZRHW is very convenient for 2D and some 3D work, as you don't have to mess too much with the Z-depth, culling and such (unless you want to).

CiNcH
27th July 2011, 06:15
I guess it has some use with some kinds of alpha blending, material layering or lighting, but those things are more for end-stage design.
Yes. I am rendering OSD textures on top of the video texture. Can I use 'D3DFVF_XYZRHW' for the video texture, apply shaders, and then render an OSD texture on top with D3DFVF_XYZ (as the OSD can be animated, so it shall to be transformable) with an alpha channel?

I am new to the whole stuff and it is just a hobby. Can you advise some good lecture for D3D9?

JanWillem32
27th July 2011, 16:17
D3DFVF_XYZRHW|D3DFVF_TEX1 will work just fine for that. It means you are using one set of texture coordinates relative to the output surface (X, Y, Z, RHW) and one set of coordinates for the sampling register bound to the source texture (X, Y), so 6 floating points per vertex point. "const MYD3DVERTEX<1> v[4]" describes a rectangle, composed of 2 triangles by drawing the vertices by index from points 0, 1 to 2 and 2, 1 to 3.
To use the example I used earlier again, after ordering the draw operation in DrawIndexedPrimitive, use "SetTexture(0, pOSDtexture);", "SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);" and DrawIndexedPrimitive again. If you want to do the alpha blend with different vertices, pre-load them to the array "const MYD3DVERTEX<1> v[8]" located in 4 to 7 and use "hr = m_pD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 4, 0, 4, 0, 2);".
Note that I didn't change any other statuses in between the two draw operations. You might want to set "SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);", for example when you're doing a 1:1 pixel mapping from source to target. Point sampling is less intensive than linear filtering, of course. In a similar way, you can decide anti-aliasing and anisotropic filtering options for each draw operation.

CiNcH
27th July 2011, 16:54
Thanks so much for your input!

I now got ps_3_0 working with vertex format 'D3DFVF_XYZRHW'. I still have some problems with vertex coordinates though. When having used 'D3DFVF_XYZ', coordinates for x and y ranged from -1 to 1, which must have been the percentage of the back buffer. This did not work with 'D3DFVF_XYZRHW'. I now use the dimensions of the back buffer in pixels with the origin (0,0). Why the difference?

You say I should use 'D3DFVF_XYZRHW' for the OSD texture as well? Even if I want to animate it? Can I use SetTransform (which I currently use to animate the OSD) with transformed vertices in the format 'D3DFVF_XYZRHW'?

Does it really make so much of a difference in performance when using an indexed buffer if we only have 4 vertices?

JanWillem32
27th July 2011, 18:58
If you use a vertex shader to modify vertices or use a pixel shader to animate it like the "sphere" and "wave" shaders, you don't have to change your base vertex statement.
If you use an Index buffer and vertex buffer, the GPU isn't halted every time to let the driver interrupt to send new vertex data. The GPU command bus instead loads it from its queue from local video memory instead.

JanWillem32
30th July 2011, 21:05
releaselog:
added the Mitchell-Netravali cubic shaders
added "detect even or odd coordinates, alternative"
updated the the complete set of chroma interpolation shaders, all include color controls now
updated Y'CbCr conversion efficiency for all shaders that perform Y'CbCr to RGB conversions

Eliminateur
31st July 2011, 19:40
feedback:
i've updated with latest pack and using the following shaders:
1-2-3 for floating surfaces Mitchell-Netravali cubic5 and r=6 sharpen complex, deband and mild denoise as pre-resize
gamma conversion for linear to wide gamut as post-resize
all compiled with PS 3.0
plus all the filters in CCC active(smooth video, dynamic range, color vibrance, flesh tone correction, edge enhance, denoise, mosquito denoise, deblocking, dynamic contrast) as i like how it outputs.

gpu usage peaks ~86% with UVD clocks but i have a feeling that it's "framing", dropped frames counter advances continuosly :(
(and i have a R5800 which should have massive ammounts of PS power available)
and another weird thing is why doesn't the card goes to 3D clocks on such high usage is beyond me....

if i disable the r=6 i get ~2 dropped frames.

disabling almost all filters in ccc don't drops much, except in long pans, looks like uvd clock ain't enough, curiously the dynamic range filter makes it drop more frrames...

JanWillem32
31st July 2011, 21:37
The filters in the video section of CCC are render items on the shader core, and just like any pixel shader, they cost some processing power when enabled.
Note that "Enforce Smooth Video Playback" isn't a video filter, but a video filter controller. When enabled, it disables some other filters once the GPU usage is near maximum capacity.

The AMD driver locks the video card to 2D clocks when DXVA is active, irrespective of the actual processing load. I use a custom profile to clock my video card a bit higher than 2D when starting MPC-HC with a 1080p or 1080i video while using DXVA. I'm fine with 2D clocks when I'm playing back 720p video, but that may be different in other cases.

The dropped frames counter will always advance a bit when menus are switched, options are enabled or disabled, while seeking, and so on. I typically get 0 dropped frames if I don't do those things.
If the dropped frames counter continues to increase during normal video playback, there's a real bottleneck.
With a HD5830 or better on reasonable clocks, your processing chain shouldn't be a problem at all. Peaks of about 86% are very reasonable.
I get peaks of up to 95% on my HD4890, usually without any frames dropped. I use an alpha version of my modified MPC-HC builds' EVR CP, and a heavier processing chain than yours (I've enabled color management).

Eliminateur
31st July 2011, 23:11
The r=6 sharpen, i enabled it on the pre-resize chain, as final resizer, is this correct?
(btw i tested adding a 9 as i didn't notice any noticeable change in video but it's definitively there now that i modify it!).
I should try some of the more "severe" values.

Also, i guess that by using the "r=6, sharpen complex, deband and mild denoise" i can safely disable all denoise and edge enhancements controls in CCC.... kind of redundant

When i mentioned dropped frames it was during regular playback. What are you using for custom clock profiles?(do you switch it by hand on 1080p or some autodetection is in place?).
Weird that i'm gettings drops on less than 90% use...
even is you use D3DEX output the GPU won't raise to 3D clocks?, seeing as in D3DEX it's essentially a 3D game....

BTW, you should add a notice on the "sharpen complex, deband and mild denoise", they don't compile on anything but PS3.0 -at least on R=6-

Why is PS 4.0 not available for compiling?, shouldn't it provide even better performance and efficiency?

Anyway, i'll continue testing!
thanks for your work and prompt responses, sorry for some of my questions as i can never get my head over colorspaces and conversions(and a lot of filters!) but i still find all these matters fascinating

JanWillem32
1st August 2011, 07:50
The "sharpen complex, deband and denoise"-type shaders can be inserted after making the RGB linear, but before resizing. Your placement is correct.
I made those shaders mostly with quality debanding in mind, the values for sharpening are very mild. (I don't like to give images the typical sharpened edges.)
For custom video card clock profiles, I use ATI Tray Tools. I generated two profiles, one intermediate for 1080p, and one with full 3D clocks for 1080i. These have a shortcut on my desktop that starts MPC-HC. Once MPC-HC exits, the video card is also set back to idle mode.
When I use a software decoder, the video card is set by default to full 3D clocks. (I generally use the intermediate profile to start the player in such a case, as it saves a bit of fan noise.)

All "sharpen complex, deband and denoise"-type shaders have the minimum required pixel shader level noted in line 9.
PS levels of 4.0 or higher are indeed more efficient, but you can only use them in DirectX 10 or higher. The renderer is sadly just DirectX 9.

CiNcH
1st August 2011, 08:51
What's the advantage of separating a scaler shader into a horizontal and vertical pass?

JanWillem32
1st August 2011, 09:39
A standard bicubic kernel samples 4 pixels in each direction. For separate horizontal and vertical passes that requires sampling 4+4 pixels. Doing that in one pass takes 16 pixels at once. For reference, see the "(inefficient one-pass)"-type shaders in the development folder.
Of course, there's some overhead in adding another pass in the chain, plus the need for a special intermediate surface (one that's only resized in one direction), but that's still less than sampling 8 pixels extra for every output pixel. The gain raises exponentially with the larger kernels that take 5 or more pixels per pass.

Eliminateur
1st August 2011, 23:41
are there any plans to make the renderer DX11?(as DX10 is kind of useless at this point...)

JanWillem32
2nd August 2011, 00:11
I don't have any objections against it, but at the moment the mixer functions, VSync functions and the subtitle renderer take precedence.

Eliminateur
8th August 2011, 00:11
Jan,
i was watching a video and noticed that it had a LOT of banding and was very noticeable, so i switched to ffdshow softdecode(RGB32+dither, deband thresh. 1.2 radius 16), disabled all shaders other than the gamma output one and it looks like a very good gradient as it should
i tried switching betweeen light and mild denoise R=6 shaders to no avail, it's VERY banded with DXVA

here's the DXVA one: http://dl.dropbox.com/u/3493496/DXVA.png
soft one: http://dl.dropbox.com/u/3493496/soft.png

any idea what do i need to tweak or do to have THAT kind of output with DXVA?

JanWillem32
8th August 2011, 01:05
Disable dynamic brightness, or any other function that's pushing the brightness so far up in the video card's control panel. Consumer video is already very limited in near black values due to the gamma and quantization, and there's also lossy compression on top of that.
The sharpening filters in control panel can also do quite a bit of harm, and I've never seen the standard denoise functions do any sort of debanding at all.
Also, all filtering settings in the the video card's control panel simply work as long as the decoder input to the EVR mixer isn't RGB. It's not an exclusive feature of DXVA.

For "sharpen complex, deband and denoise"-type shaders, you can raise the "NoiseLevel" value for a more agressive deband and denoise. There's also "GammaCompensation", but lowering it can be harsh on low-light, poor quality video.
Line 21: // GammaCompensation, interval [1, 2], default 1.5, the gamma compensation factor to diminish denoising on darker pixels, a factor 1 will use the same grade of filtering on darker and lighter pixels, the current standards for consumer-grade video are lacking in dynamics for the lower brightness range, so a factor 1 will usually cause too much fitering on darker pixels

Note, as usual, any proper debanding requires better working surfaces than the default X8R8G8B8 in the renderer chain.

dukestravels07
8th August 2011, 23:23
Hi Jan. I was wondering if you could give me a basic idea of what shaders to use with my setup?.
I've read through the thread and while I get the basics, some of it is totally confusing. I have a very basic HTPC setup. It consists of a visiontek ATI HD3650 agp card. I run mpc-hc with vmr9 renderless and dxva works fine.

I have a really crap old projector (SL2U) that has a native res of 800x600, so most of the films I have are avi with roughly DVD like quality...some are VHS quality.

I was wondering how I could get the best possible quality using your shaders?

I have no idea about "gamma conversion for linear RGB" is this something I need to use?

Will yv12 chroma upsampling improve crap avi's?

Basically if you can give a basic list of shaders and in what order they should go, in order to imrpove my videos id be grateful.

Thanks in advance.

JanWillem32
9th August 2011, 01:26
There's unfortunately no magic filter that will make a display look like it has a higher resolution. We can only filter the video.
Intermediate conversion to linear gamma is used to prevent darkening artifacts on every processing step. We generally do encoded video gamma -> linear gamma -> display gamma.
Chroma up-sampling shaders are a trick to get video input where chroma up-sampling was skipped to be up-sampled by one of the 4 methods. Your video card will skip chroma up-sampling when a surface mode other than X8R8G8B8 is used with the VMR-9 or EVR mixers. (10-bit out, HFPP, FFPP settings for MPC-HC)

My settings will be a bit heavy for your setup but it's better to start with more and take away things later.
Feel free to relax Full Floating Point Processing for Half, and replace "r=6, sharpen complex, deband and denoise" for something less extreme. There are plenty of choices to make your own working chain. It's just a matter of taste, but in general, don't try to apply two similar filters in one chain. It's usually better to edit settings in one shader to make it lighter or heavier in an aspect. Other than that, try a lot. Even messing around with some of the joke shaders can be very interesting.

Renderer settings I use in MPC-HC's EVR CP:
D3D Full Screen Mode, 10-bit RGB Output, Full Floating Point Processing, Disable desktop composition (Aero)

Shader chain:
1. RGB to Y'CbCr for SD&HD video input for floating point surfaces
2. special 4÷2÷0 to 4÷2÷2 intermediate Catmull-Rom spline5 chroma up-sampling for SD&HD video input
3. special 4÷2÷2 Catmull-Rom spline5 chroma up-sampling for SD&HD video input (linear output enabled, sometimes I also set colorfulness gamma to lower a high colorfulness on some video sources)
r=6, sharpen complex, deband and medium denoise,
Post-resize:
gamma conversion of linear RGB to wide gamut RGB for floating point surfaces
final pass: color management with an ICC profile installed system-wide and random ordered dithering

mindbomb
28th August 2011, 02:56
C:\Program Files (x86)\Media Player Classic - Home Cinema\memory(64,29): warning X3206: implicit truncation of vector type
C:\Program Files (x86)\Media Player Classic - Home Cinema\memory(64,45): warning X3206: implicit truncation of vector type
C:\Program Files (x86)\Media Player Classic - Home Cinema\memory(64,63): warning X3206: implicit truncation of vector type
C:\Program Files (x86)\Media Player Classic - Home Cinema\memory(85,12): error X3014: incorrect number of arguments to numeric-type constructor

i get these errors when creating the bilinear 4 2 0 chroma filter.
anything to worry about?

Eliminateur
28th August 2011, 03:11
mindbomb, check the PS version you're compiling the shaders with the shader editor, use the highest you can based on your hardware(usually ps 3.0 by now)

JanWillem32
28th August 2011, 10:43
I already noticed that the bilinear up-samplers were broken when I was integrating them in the latest MPC-HC tester build. I waited some time to get a nice set of fixes and new shaders ready.

Changelog:
corrected "bilinear chroma up-sampling and color controls for SD&HD video input"
improved performance for many Y'CbCr mode shaders

YCbCr-type sharpen complex test
I've tried something new. I've adapted r=4, r=5 and r=6 sharpen complex, deband and medium denoise to Y'CbCr-mode shaders. So far I've been very satisfied with its debanding capabilities and performance, so I'm asking if others would like to test these, too. For changing the debanding and denoising strength, just edit the value for "NoiseLevel".
For those that use the chroma up-sampling sets, the alternatives for the three 4:2:2 up-sampling shaders are included. Others can use one of the two "RGB to Y'CbCr for SD&HD video input"-type shaders to pre-process to Y'CbCr mode.
If anything needs correction, please tell me.

mindbomb
28th August 2011, 14:22
thanks, the bilinear chroma shader from 1.4 works perfectly

Qaq
28th August 2011, 14:40
Personally, I found that *correct* HQ chroma upsampling provides agressive colors with my setup. Same thing with madVR, even for FullHD videos (most of them). I've disabled all the adjustments in video driver, my TV doesn't allow color control in PC mode, so I can only hope for perfect color processing in video renderer. Trying to avoid that color madness I found that w/o chroma shaders picture looks much close to natural. Need to try NN chroma scaler in madVR too. :devil:

Eliminateur
28th August 2011, 22:35
are those in the development folder or the production folders?

I already noticed that the bilinear up-samplers were broken when I was integrating them in the latest MPC-HC tester build. I waited some time to get a nice set of fixes and new shaders ready.

Changelog:
corrected "bilinear chroma up-sampling and color controls for SD&HD video input"
improved performance for many Y'CbCr mode shaders

YCbCr-type sharpen complex test
I've tried something new. I've adapted r=4, r=5 and r=6 sharpen complex, deband and medium denoise to Y'CbCr-mode shaders. So far I've been very satisfied with its debanding capabilities and performance, so I'm asking if others would like to test these, too. For changing the debanding and denoising strength, just edit the value for "NoiseLevel".
For those that use the chroma up-sampling sets, the alternatives for the three 4:2:2 up-sampling shaders are included. Others can use one of the two "RGB to Y'CbCr for SD&HD video input"-type shaders to pre-process to Y'CbCr mode.
If anything needs correction, please tell me.

JanWillem32
29th August 2011, 07:18
@Qaq: That's odd. With the sharper resizers, like the Mitchell-Netravali cubic and Catmull-Rom spline implementation I've used, over-saturation on some chroma borders is possible (but very rare). With resizers that can only blur, like the cubic B-Spline and bilinear implementation I've used, that's not possible.
I wonder what your TV is doing to the signal. When the RGB 4:4:4 full range output of the renderer is left unprocessed by the display device (no digital processing, only digital-to-analog conversion for the panel), any form of chroma up-sampling in the renderer should give a better picture over nearest neighbor (especially if full picture resizing or aspect ratio correction is used by the renderer).
It's known that in some situations the renderer output is converted afterwards, lowering the output quality. Can you test the "draw grid coordinates" shader? It should draw single-pixel wide RGB lines horizontally and vertically when full picture resizing and aspect ratio correction are disabled. If there's something wrong with the processing after the renderer output, the lines will be imperfect.

@Eliminateur: The full directory listing of the normal download is in the OP, the "YCbCr-type sharpen complex test" is a separate download.

Qaq
29th August 2011, 10:07
Jan, thanks for the tip, of course I'll try to test my display with that "draw grid coordinates" shader.

burfadel
29th August 2011, 21:24
I've noticed with the sharpen, deband, denoise filters (I use r=6), the following:

// VideoGamma, interval [2., 3.], default 2.4, the video gamma input factor used to convert between the video input RGB and linear RGB during pre-processing
#define VideoGamma 2.4

Results in a very very dark image. If I set the videogamma to 1, its fine (original)...

JanWillem32
29th August 2011, 22:43
The 2.4 is perfectly fine as it is, you are looking for "LinearRGBOutput", which has a default value of 1. You can also reverse the gamma setting just before dithering (insert it as a post-resize shader as the last item), so the resizer and other shaders in between can work on linear RGB.

burfadel
29th August 2011, 23:59
hmmm, don't know why, but I either have to set the videogamma as 2.4 or set '#define LinearRGBOutput' as 0, regardless of how I set it!

Its only with shader pack v1.4

JanWillem32
30th August 2011, 07:28
Only the version in the "YCbCr-type sharpen complex test" changes the gamma to linear RGB on output by default. The regular one already expects linear RGB input (it only uses the gamma value for brightness estimation).
What setup do you use? I might need to edit some parts of the code if it's really broken.

Qaq
30th August 2011, 18:20
Can you test the "draw grid coordinates" shader? It should draw single-pixel wide RGB lines horizontally and vertically when full picture resizing and aspect ratio correction are disabled. If there's something wrong with the processing after the renderer output, the lines will be imperfect.
Tried the shader with 1080 video. Picture looks exactly the same in MPC-HC and in image viewer.
http://lostpic.net/thumbs/5a4f2f5483a7601144e257d3565c1ba0.png (http://lostpic.net/?view=5a4f2f5483a7601144e257d3565c1ba0)
Can't say I understand what to call perfect and imperfect here, but lines seems straight at least.
BTW, I found that picture looks completely different if I switch HDMI input between YCC and RGB. Seems like this shader is good test for HDMI chroma sub-sampling bug too.

JanWillem32
31st August 2011, 07:53
The "draw grid coordinates" is exactly to test for chroma sub-sampling errors. The other function is a geometry checkup. If the lines are not projected as single-pixel wide on screen, because of errors with overscan/underscan, resolution or geometry settings, the lines will be blended. Failure to map pixels 1:1 to the screen is a common problem that causes visible errors.

JanWillem32
14th September 2011, 09:27
I've just added version 2 of the YCbCr-type sharpen complex test.
These shaders are a bit better at banding detection, especially for chroma. They were only somewhat difficult to configure a reasonable sharpness to debanding ratio for.
For those that use the chroma up-sampling sets, the alternatives for the three 4:2:2 up-sampling shaders are included. Others can use one of the two "RGB to Y'CbCr for SD&HD video input"-type shaders to pre-process to Y'CbCr mode.
If anything could use improvement, please tell me.

TheElix
14th September 2011, 09:48
Please, could you tell me what differs this YCbCr-type version from the usual one and when one should prefer it over the usual version and what benefits it would give?

JanWillem32
14th September 2011, 11:02
The regular ones work on linear RGB. That's near-optimal for input with a reasonably linear response, a large gamut, a well-defined color interval at [0, 1] and no chroma sub-sampling issues. Unfortunately, consumer-grade video fails on all four accounts.
It's usually chroma sub-sampled. I've seen reasonably proper blu-ray masters that greatly overstep their nominal range (Y'CbCr, interval [16, 235], [16, 240], [16, 240]). The source gamut of HD video is limited to just sRGB, the gamut of SD video is even less than that. The Cb and Cr channels are reasonably linear (these are usually overpowered in presence by the luma channel in the matrix), but the Y' channel is a very bad approximation to linear lightness.
Adapting the filter to work on flaws of the source video in Y'CbCr colors is a good idea, but designing the shader was hard. The fist few versions I made looked terrible, these couldn't keep a good distinction in the areas to deband.
I'm actually pretty satisfied with the filter as it is now, but perhaps the main function could use some extra customization user settings apart from the regular "NoiseLevel".

TheElix
14th September 2011, 14:56
On what content do you recommend this filter to be used? I want to make some screenshot comparisons.

JanWillem32
14th September 2011, 15:11
Any standard Y'CbCr video will do fine. Try a variety, while adjusting "NoiseLevel" to a suitable value for each. Of course, the values for sharpening are by user preference. The current version is very sensitive to the sharpening parameters. A little too low blurs too much, a little too high and the typical sharpening artifacts become very visible.

TheElix
14th September 2011, 15:18
Aren't all DVD/BD content Y'CbCr? As well as TV translations... Also, adjusting parameters in a shader for each video is a little extreme. But for the sake of experiment....

JanWillem32
14th September 2011, 15:36
Pretty much all consumer-grade digital video uses Y'CbCr. I wouldn't use this kind of filter on superior formats, like when loading a standard BMP through the still image filter, for instance.
I've always supplied 5 versions of the same shader, each with only the "NoiseLevel" parameter changed (values .625, .75, 1, 1.5 and 2.5).

TheElix
14th September 2011, 21:16
Regular chain: http://img7.imageshack.us/img7/6919/regularshaders.png
With YCbCr-type 3. special 4÷2÷2 cubic B-spline5 chroma up-sampling: http://img190.imageshack.us/img190/6629/ycbcrtypeshaders.png

Qaq
14th September 2011, 22:49
Yeah, I remember it was red then I did something wrong. TheElix, make sure you haven't missed anything from the shader code.

TheElix
14th September 2011, 23:53
Nothing is missed with ctrl+A, ctrl+V.

JanWillem32
15th September 2011, 05:17
The regular type requires pre-processing to linear RGB by a "gamma conversion of video RGB to linear RGB"-type shader or integrated gamma function. The regular type will not change that gamma setting, so correction of gamma just before display output is required, too.
The Y'CbCr-type shader requires Y'CbCr pre-processing by a "RGB to Y'CbCr for SD&HD video input"-type shader (used on non-linear input). For those that already use multi-pass chroma interpolation, it would be rather silly to do that conversion twice, so I added alternatives to step 3, and moved the set of color controls. The Y'CbCr-type shader outputs linear RGB by default, but can be reconfigured easily.

CeeJay.dk
30th November 2011, 00:16
I posted my LumaSharpen shader (http://forum.doom9.org/showthread.php?p=1541796#post1541796) in another thread earlier and today I found this thread.

My shader is basically Y' version of Sharpen Complex but optimized for speed (still achieves better quality than the original) since it's primarily meant to be used for gaming.
I'm using an injector that allows me to do post-processing of the screenbuffer of any Direct3d game and the sharpen shader helps with the many upscaled textures you find in a game.

It's my first shader ever and my first real bit of programming I've done since school 16 years ago, but I feel I've already acomplished a lot in the few days I've been working on it.

Let me know what you think.

JanWillem32
5th December 2011, 01:26
That's quite interesting. I'll take a good look when I have more time. A quick glance at the code shows sqrt over mul. That's usually an improper way to deal with vectors. Try using abs on the delta values, next you can try using the more regular dot or length intrinsics. Be careful with pixel radius. The pixel shader sampler can be set to bilinear (or a few other functions on top of that), or in the case of MPC-HC, nearest neighbor. When sampling pixels, only use whole pixel sizes as distances. At the end, there's a function that uses pow with a floating-point exponent. That function will output undefined values if negative values are input. See a few of my shaders for reference on processing such values
Lastly, I've made a similar function: "sharpen\unsharp luma mask for SD&HD video". (Altough I've never really understood the black compensation, and I don't care much for versions without deband.) The shaders for the YCbCr-type sharpen complex test are a lot more advanced (and heavy), but maybe you can get some ideas from those for some of your own code. Note that the parameters are a bit extreme in those, I'm using a somewhat edited version of "r=6" myself... Might as well post that:// (C) 2011 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

#define NoiseLevel .75
#define Blur NoiseLevel/64.
#define EdgeSharpen 1.75*Blur
#define Sharpen0 .0625
#define Sharpen1 .140625
#define Sharpen2 .31640625
#define Sharpen3 .2109375
#define Sharpen4 .140625
#define Sharpen5 .09375
#define VideoGamma 2.4
sampler s0;
float2 c1 : register(c1);
#define sp(a, b) tex2D(s0, tex+c1*float2(a, b))
#define H0 Sharpen0*(1.125-dv3)
#define H1 Sharpen1*(1.125-dv3)
#define H2 Sharpen2*(1.125-dv3)
#define H3 Sharpen3*(1.125-dv3)
#define H4 Sharpen4*(1.125-dv3)
#define H5 Sharpen5*(1.125-dv3)
#define qp(a, b) ((dv = max(max((dv3 = abs(a)).x, dv3.y), dv3.z)) > b)?
#define D0d(a, b) qp((s1+b)/2.-a, ES) s1*(H0+1.)-a*H0
#define D0o(a, b) qp((s1+b)/3.-a, ES) s1*(H0+1.)-a*H0
#define D1d(a, b) (dv > BN)? (t1+a)/1.125*(H1+1.)-b*H1
#define D1o(a, b) (dv > BN)? (t1+a)/1.125*(H1+1.)-b/2.*H1
#define D2d(a, b, c) qp((a+c)/3.-b, BN) (t1+a+b)/2.125*(H2+1.)-c/2.*H2
#define D2o(a, b, c) qp((a+c)/3.-b/2., BN) (t1+a+b)/3.125*(H2+1.)-c/2.*H2
#define D3d(a, b, c, d) qp((b+d)/5.-c/2., BN) (t1+a+b+c)/4.125*(H3+1.)-d/4.*H3
#define D3o(a, b, c, d) qp((b+d)/6.-c/2., BN) (t1+a+b+c)/5.125*(H3+1.)-d/4.*H3
#define D4d(a, b, c, d) qp((b+d)/6.-c/4., BN) (t1+a+b+c)/8.125*(H4+1.)-d/4.*H4
#define D4o(a, b, c, d) qp((b+d)/5.-c/4., BN) (t1+a+b+c)/9.125*(H4+1.)-d/3.*H4
#define D5d(a, b, c, d) qp((b+d)/8.-c/4., BN) (t1+a+b+c)/12.125*(H5+1.)-d/4.*H5
#define D5o(a, b, c, d) qp((b+d)/8.-c/3., BN) (t1+a+b+c)/12.125*(H5+1.)-d/4.*H5
#define D6(a) (t1+a)/16.125
#define Dd(a, b, c, d, e, f) (D0d(a, b) : D1d(a, b) : D2d(a, b, c) : D3d(a, b, c, d) : D4d(a+b, c, d, e) : D5d(a+b+c, d, e, f) : D6(a+b+c+d+e+f))
#define Do(a, b, c, d, e, f) (D0o(a, b) : D1o(a, b) : D2o(a, b, c) : D3o(a, b, c, d) : D4o(a+b, c, d, e) : D5o(a+b+c, d, e, f) : D6(a+b+c+d+e+f))
float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 s1 = sp(0, 0).rgb;
float3 s2 = sp(-1, -1).rgb;
float3 s3 = sp(0, -1).rgb;
float3 s4 = sp(1, -1).rgb;
float3 s5 = sp(-1, 0).rgb;
float3 s6 = sp(1, 0).rgb;
float3 s7 = sp(-1, 1).rgb;
float3 s8 = sp(0, 1).rgb;
float3 s9 = sp(1, 1).rgb;
float3 r2 = sp(-2, -1).rgb;
float3 r3 = (sp(-1, -2)+sp(0, -2)).rgb;
float3 r4 = sp(1, -2).rgb;
float3 r5 = (sp(-2, 1)+sp(-2, 0)).rgb;
float3 r6 = (sp(2, 0)+sp(2, -1)).rgb;
float3 r7 = sp(-1, 2).rgb;
float3 r8 = (sp(0, 2)+sp(1, 2)).rgb;
float3 r9 = sp(2, 1).rgb;
float3 q2 = (sp(-2, -2)+sp(-3, -1)).rgb;
float3 q3 = (sp(-1, -3)+sp(0, -3)).rgb;
float3 q4 = (sp(2, -2)+sp(1, -3)).rgb;
float3 q5 = (sp(-3, 1)+sp(-3, 0)).rgb;
float3 q6 = (sp(3, 1)+sp(3, 0)).rgb;
float3 q7 = (sp(-1, 3)+sp(-2, 2)).rgb;
float3 q8 = (sp(0, 3)+sp(1, 3)).rgb;
float3 q9 = (sp(2, 2)+sp(3, -1)).rgb;
float3 p2 = (sp(-4, -1)+sp(-4, -2)+sp(-3, -2)+sp(-3, -3)).rgb;
float3 p3 = (sp(-2, -3)+sp(-2, -4)+sp(-1, -4)+sp(0, -4)).rgb;
float3 p4 = (sp(2, -3)+sp(3, -3)+sp(1, -4)+sp(2, -4)).rgb;
float3 p5 = (sp(-4, 2)+sp(-3, 2)+sp(-4, 1)+sp(-4, 0)).rgb;
float3 p6 = (sp(4, 0)+sp(4, -1)+sp(3, -2)+sp(4, -2)).rgb;
float3 p7 = (sp(-2, 4)+sp(-1, 4)+sp(-3, 3)+sp(-2, 3)).rgb;
float3 p8 = (sp(0, 4)+sp(1, 4)+sp(2, 4)+sp(2, 3)).rgb;
float3 p9 = (sp(3, 3)+sp(3, 2)+sp(4, 2)+sp(4, 1)).rgb;
float3 o2 = (sp(-5, -1)+sp(-5, -2)+sp(-4, -3)+sp(-3, -4)).rgb;
float3 o3 = (sp(-2, -5)+sp(-1, -5)+sp(0, -5)).rgb;
float3 o4 = (sp(4, -3)+sp(3, -4)+sp(1, -5)+sp(2, -5)).rgb;
float3 o5 = (sp(-5, 2)+sp(-5, 1)+sp(-5, 0)).rgb;
float3 o6 = (sp(5, 0)+sp(5, -1)+sp(5, -2)).rgb;
float3 o7 = (sp(-2, 5)+sp(-1, 5)+sp(-3, 4)+sp(-4, 3)).rgb;
float3 o8 = (sp(0, 5)+sp(1, 5)+sp(2, 5)).rgb;
float3 o9 = (sp(3, 4)+sp(4, 3)+sp(5, 2)+sp(5, 1)).rgb;
float3 n2 = (sp(-4, -4)+sp(-5, -3)+sp(-6, -2)+sp(-6, -1)).rgb;
float3 n3 = (sp(0, -6)+sp(-1, -6)+sp(-2, -6)+sp(-3, -5)).rgb;
float3 n4 = (sp(4, -4)+sp(3, -5)+sp(2, -6)+sp(1, -6)).rgb;
float3 n5 = (sp(-5, 3)+sp(-6, 2)+sp(-6, 1)+sp(-6, 0)).rgb;
float3 n6 = (sp(6, 0)+sp(6, -1)+sp(6, -2)+sp(5, -3)).rgb;
float3 n7 = (sp(-1, 6)+sp(-2, 6)+sp(-3, 5)+sp(-4, 4)).rgb;
float3 n8 = (sp(3, 5)+sp(2, 6)+sp(1, 6)+sp(0, 6)).rgb;
float3 n9 = (sp(6, 1)+sp(6, 2)+sp(5, 3)+sp(4, 4)).rgb;

float dv;
float3 dv3;
float BN = Blur;
float ES = EdgeSharpen;
float3 t1 = s1/8.;
float3 t0 = ((Dd(s2, r2, q2, p2, o2, n2)+Do(s3, r3, q3, p3, o3, n3)+Dd(s4, r4, q4, p4, o4, n4)+Do(s5, r5, q5, p5, o5, n5)+Do(s6, r6, q6, p6, o6, n6)+Dd(s7, r7, q7, p7, o7, n7)+Do(s8, r8, q8, p8, o8, n8)+Dd(s9, r9, q9, p9, o9, n9))/8.);
t0 = float3(t0.x+1.5748*t0.z, dot(t0, float3(1, -.1674679/.894, -.4185031/.894)), t0.x+1.8556*t0.y);// HD Y'CbCr to RGB
//t0 = float3(t0.x+1.402*t0.z, dot(t0, float3(1, -.202008/.587, -.419198/.587)), t0.x+1.772*t0.y);// SD Y'CbCr to RGB
float3 sbl = sign(t0);
t0 = sbl*pow(abs(t0), VideoGamma);
return t0.rgbb;
}

CruNcher
5th December 2011, 03:23
Sounds cool CeeJay thx, i wonder if it is comparable to mirillis implementation in performance/quality they use their own Direct 3D renderer + Shader and in terms of GPU resources it's damn efficient and looks comparable to Sharpen Complex 2 though it seems to work different :)
they call it "Detail Boost" http://mirillis.com/en/products/picture2.html it deblurs very heavy quantized stuff very efficiently with low GPU resources tests based on Sandy Bridge HD2000 (GT1) 6 EU upto 1080p

CeeJay.dk
5th December 2011, 18:55
A quick glance at the code shows sqrt over mul. That's usually an improper way to deal with vectors. Try using abs on the delta values, next you can try using the more regular dot or length intrinsics.

if (sqrt( mul(delta1,delta1) + mul(delta2,delta2)) > SharpenEdge) //?? Verify that the mul and sqrt aren't just there to get a positive value.

That bit of code is part of the edge detection from Sharpen Complex 2.
I agree .. multiplying a variable with itself and then taking the square root is a silly roundabout way to get a positive number when you can just use abs().

I don't use that part anymore. Mainly because edge detection was detecting large differences in contrast and applying less sharpening to those areas (well at least that how I used it .. I prefer edges smooth, not sharp) if the difference was above a certain threshold. But this causes some pixels that were sometimes over the threshold and sometimes under, to flicker which was very distracting to my eyes, so I turned it off.

I now just clamp the sharpening effect to a set maximum and this prevents edges from getting over-sharpened and it's much simpler and doesn't flicker.
There may be better way of limiting the sharpen effect from creating harsh artifacts and haloing, but for now I'm satisfied with just clamping the effect.

I may use the edge detection later if I can improve it or just throw it out, but for now I've left it in the code, but disabled it.


When sampling pixels, only use whole pixel sizes as distances.

But if I did that, then I couldn't exploit the hardware filtering trick that I use to greatly increase the speed over the original sharpen complex code.

Taking advantage of that is the best part of my shader.
When I sample on the edges of a pixel I get an average of the four pixels surrounding it. If I move the sampling point slightly I can adjust the weights of the pixels sampled.
Doing it this way even gets rid of the instructions that calculated the weights before .. those calculations are now free.

See http://prideout.net/archive/bloom/#Sneaky and http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ for more detailed explanations of what I'm doing.

I'm currently also considering more exotic sampling patterns as well as using mipmap samples, to see if I can get a very large gaussian blur using very few samples.

For now I'm satisfied with using just 5 samples to get a 9-tap equivalent, but if I later wanted to try my hand at a local contrast enhancement (http://www.cambridgeincolour.com/tutorials/local-contrast-enhancement.htm) shader I would need a much larger blur.
You're using a huge amount of samples - Local contrast enhancement might be something you would want to try.

I use my shaders for games though, and I need them to be very efficient, so I'm holding off on that until I find fast way to do very large blurs.
Maybe box blur or one of the blurs from http://incubator.quasimondo.com/ - Stack blur, Superfast blur or Son of Gauss.


At the end, there's a function that uses pow with a floating-point exponent. That function will output undefined values if negative values are input. See a few of my shaders for reference on processing such values

//done = float4(pow(done, 1.0 / 2.2 )); Convert a sRGB colorspace to non-linear gamma 2.2 - Turned off because of precision errors

I was experimenting with doing the calculations in linear colorspace to see if that would improve the quality any. It produced errors instead. It should not use any negative values as input, but I may have overlooked something and you're right.
I'll take a look your code to see how you do it. Reading your code is not that easy though as you don't use comments much.

CeeJay.dk
6th December 2011, 23:04
Sounds cool CeeJay thx, i wonder if it is comparable to mirillis implementation in performance/quality they use their own Direct 3D renderer + Shader and in terms of GPU resources it's damn efficient and looks comparable to Sharpen Complex 2 though it seems to work different :)
they call it "Detail Boost" http://mirillis.com/en/products/picture2.html it deblurs very heavy quantized stuff very efficiently with low GPU resources tests based on Sandy Bridge HD2000 (GT1) 6 EU upto 1080p

I haven't seen mirilis Splash before, but it does look good. I'd love to know what technique they use.

I don't know how LumaSharpen compares to Detail boost, but properly tweaked it's slightly better than Sharpen Complex 2 qualitywise and much faster.

Between LumaSharpen, Sharpen Complex and Jan's Sharpen/Denoise/Deband shaders, Jan's probably has the best quality but also takes a lot of GPU time.

jokerb47
21st December 2011, 20:55
How to use these PS for image viewing?

Qaq
22nd December 2011, 06:51
Read first post:
To make a pixel shader work in MPC-HC:....

CeeJay.dk
24th December 2011, 12:09
I've noticed my shader in MPC seems to stretch the image from the center with about a pixels length. But only does this in MPC, not when used in combination with the dx9 shader injector i'm developing it for.
Why is that ?

I suspect I may need to change something in MPC's render settings or may force it to use bilinear filtering, but I'm not sure.

JanWillem32
28th December 2011, 01:58
@CeeJay.dk: Sorry for the delay.
I think it's a good thing you removed that part of the code you mentioned.
The original "Sharpen Complex 2" does indeed produce aliasing artifacts (along with banding and non-uniform filtering in its input to output color spectrum). With a branch in the code path implemented like that it's pretty inevitable.
I'm also familiar with the difficulty of getting good parameters for filter parts to get a proper, uniform response with various scenes and also varying video quality of course.

There's no speed increase by filtering sampling on 4 pixel borders using a bilinear sampler state over filtering sampling on 9 pixels using a nearest neighbor (point) sampler state (for this case). Shaders are interpreted by the display driver before being transported to the GPU's command cue and execution caches. Resolving a bilinear sampler state is done on the shadercore, the same processor chains that process the shaders themselves.
As usual, this is pretty hard to measure. Shadercores are superscalar engines, meaning that the pipelines can process multiple operations simultaneously, as long as those are in independent parts of the pipeline (doing different types of operations).
An example of that can be seen in the disassembly of a pixel shader with mixed code and multiple pixels being sampled. Under level 3.0 compiling (DirectX 9.0c) and onwards, sampling commands will be spread out over the length of the code. That's flow control (there are even some compiler flags to influence it). Sampling pixels is slow, and during sampling to a register, simple arithmetic can be done on independent registers (such as values from previous sample instructions). This means that applying a simple filter, whether it's from a bilinear averaging from a sampler state or simple self-written code, it's not likely to have any impact on the global speed of rendering at all.
(Note 1: Enabling flow control generally increases the total instruction count a bit but executes faster due to better pipeline utilization.
Note 2: DirectX 10 and onwards supports the intrinsics Sample() and Load(). Load() ignores sampler states and is better optimized by the compiler and driver because of that.)
In the pages you posted, both code for an OpenGL target (DirectX 9 and 10+ handle things quite a bit different). There's also no disassembly or data on globally active sampler states posted with any of the functions unfortunately. A difference in code target vectorization (four floats in a register usage for arithmetic functions, instead of fewer, or even only one float at a time) and serialization (flow control, mixed instructions using independent registers will take less time on average than instructions that repeat or executes while re-using the same registers multiple times in succession) can point out important performance issues.
(Note 3: SSE code on the CPU behaves pretty much the same way. The registers on the GPU's shadercore and the CPU's SSE core even support the same data configurations (with two rare exceptions). Just don't use any integer arithmetic on the GPU if it's not really necessary, the performance is very bad.
Note 4: Next to instruction vectorization and serialization there's parallelization, achieved trough rendering many 4×4 output pixel chunks in separate threads on the many execution units of the shadercore.)

Using mipmaps as a source for square-blurred samples is an idea I looked into earlier as well. I render from and to usual render-target textures. When I want to use the mip levels of such a texture, I'll have to order the device to generate it from the top-level surface that was just rendered. That's because the mip levels are not written during rendering at all.
I haven't had much success with this kind of mipmap usage at all. The blur is low-resolution and purely square which made it look aliased. If you've found a better-looking method, please share it. I'm still looking at integrating efficient debanding, sharpening and other basic functions for the internal video renderers.

Local contrast enhancement is indeed very interesting, so thank you for the link. This method solves some of the problems with a single box sampling area to unsharp mask (as noted in the text).
The parts "Complications" and "Further reading" are informative as well, although "Complications" could be spiced up a bit more in a technical sense. The first part describes the very common distortions found when rendering in a non-uniform colorspace. The suggestions to the solution are insightful, but don't go all the way. The suggested LAB colorspace is designed scale visually linear internally to luminance and chrominance dimensions. It's not mathematically linear or linear to lightness. In most of its encoded forms it also can't cover the entire range visible colors. For professional purposes the uniform (and directly related) color spaces XYZ an xyY are often used for rendering. (I'm also thinking it would be a good format to use by the internal renderer of MPC-HC, too. Although it can't be used with the 8- or 10-bit buffer formats.)
The second issue is the one I saw first in the sample pictures. Damage to the dynamic range is really common with image filters. If you butcher a picture with those bad enough, you can't even do a successful 'repair' filter pass afterwards (even with the most ideal precision intermediate picture buffers). As I understand, the pictures are dramatized to show a stronger effect of the filter than it is likely to be ever used.
I think this function could benefit from a convolution function: a gradual function to transform measured area sharpness to a factor used to directly blur or sharpen by that amount (possibly evaluating it for multiple directions from the base pixel). I'll take a look if I can write a prototype pixel shader based on this.

About the pow() intrinsic function; the compiler will warn that will not work properly on negative numbers. I used to have problems with it too, before I found out you can simply carry over the sign bits with the sign() intrinsic. After that, it behaved exactly as expected.

About writing comments in the code, take a look at the links in the opening post of this thread or the code packages in my folder. As far as I know, I make plenty of comments in my code.


About quality of the various sharpening filters; I think a very good balance in efficiency and quality could be achieved using an integrated multi-pass solution coded natively in the renderer, instead of in a single pixel shader. As I prefer to measure the sharpness relative to the current pixel in multiple directions and process blurring or sharpening per direction as well, generating a look-up map or similar optimization like that is difficult. I'd love to try some new methods that are a bit lighter than my current set. I know that that takes a flash of inspiration, and then a lot of patience to actually see any decent results.

Finally, to answer your latest post;
I've specifically hard-coded the renderer to only enable a bilinear sampler state on the filter passes for the color management's look-up table, automatically for resizing of subtitles and by (one) user setting for the main video resizing passes. (In the version of the renderer I edited, I also removed it for the main video resizing pass.)
I don't exactly remember how the renderer in the trunk build managed vertices at all. When I dumped the renderer core and imported a new one, I made the vertex caches indexed. After that, I never had any problems with it anymore. (The version in the trunk build can't even manage two-pass resizing.) AFAIK the vertices I coded have no displacement problems, but I can't guarantee that for the renderer in the trunk build.


I hope I didn't bore anyone with my recent walls of text on this forum... I'm just trying to help people a bit after being away for a while.:)

CeeJay.dk
31st December 2011, 13:37
There's no speed increase by filtering sampling on 4 pixel borders using a bilinear sampler state over filtering sampling on 9 pixels using a nearest neighbor (point) sampler state (for this case).
...
As usual, this is pretty hard to measure.


AMDs GPU Shaderanalyzer, in-game FPS meters, and using MSI Afterburner to measure GPU load, all tell me that using 4 texture fetches is faster than using 9.


Sampling pixels is slow, and during sampling to a register, simple arithmetic can be done on independent registers (such as values from previous sample instructions). This means that applying a simple filter, whether it's from a bilinear averaging from a sampler state or simple self-written code, it's not likely to have any impact on the global speed of rendering at all.


If you are saying that it often doesn't matter to optimize the number of ALU instructions, because the bottleneck when sampling several pixel is going to be texture fetches then I already know.
GPU Shaderanalyzer reports that texture fetches are the bottleneck on 11 of the 17 AMD cards is displays statistics about.

Just don't use any integer arithmetic on the GPU if it's not really necessary, the performance is very bad.

I know .. I won't.

I hope I didn't bore anyone with my recent walls of text on this forum... I'm just trying to help people a bit after being away for a while.:)

I'm not bored .. in fact I have more to comment on it , I just don't have time right now .. it's New Years.

Happy New Year!

P.S.

I thought you might like to see how I'm progressing .. this is the latest iteration of LumaSharpen (there are still lots more to be done .. I have so many ideas - I'll share some later if I get the time.)

/*
____________________

LumaSharpen 1.1.2
____________________

by Christian Cann Schuldt Jensen ~ CeeJay.dk

Based on Sharpen Complex 2 from Media Player Classic
(I have rewritten most of the code by now though)

It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image.
It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts.

This is similar to converting an image to LAB colorspace and using Unsharp Mask on the Lightness channel in Photoshop.

Compiles with both PS 2.0 and 3.0 (Faster with 3.0)
*/

// .----------------------------------------------------._User settings_.---------------------------------------------------.

// -- Sharpening --
#define offset_bias 1.0 // I suggest a value between 0.0 and 2.0 - default is 1.0
#define sharp_strength 0.5 // Strength of the sharpening - You should probably use something between 0.2 and 2.0 - default is 0.5
#define sharp_clamp 0.015 // Limits maximum amount of sharpening a pixel recieves - Default is 0.015

#define pattern 2 // Choose a sample pattern ( 1, 2 or 3 )

// .--------------------------------------------------._Defining constants_.------------------------------------------------.

/* For use with SMAA injector.
#define s0 colorTexG
#define px BUFFER_RCP_WIDTH
#define py BUFFER_RCP_HEIGHT
*/


// For use with Shaderanalyzer and MPC-HC
sampler s0 : register(s0);
float4 p0 : register(c0);
float4 p1 : register(c1);

#define width (p0[0])
#define height (p0[1])

#define px (p1[0])
#define py (p1[1])

//#define dx (offset_bias*px)
//#define dy (offset_bias*py)



#define CoefLuma float4(0.2126, 0.7152, 0.0722, 0) // BT.709 & sRBG luma coefficient (Monitors and HD Television)
//#define CoefLuma float4(0.299, 0.587, 0.114, 0) // BT.601 luma coefficient (SD Television)
//#define CoefLuma float4(0.3333, 0.3334, 0.3333, 0) // Equal weight coefficient

#define sharp_strength_luma (CoefLuma * sharp_strength)

// .------------------------------------------------------._Main code_.-----------------------------------------------------.

//float4 SharpenPass( float2 tex )
float4 main( float2 tex : TEXCOORD0 ) : COLOR // Use with Shaderanalyzer and MPC-HC
{

// -- Get the original pixel --
float4 ori = tex2D(s0, tex); // ori = original pixel

// [ NW, , NE ] Each texture lookup (except ori)
// [ ,ori, ] samples 4 pixels
// [ SW, , SE ]

// -- Pattern 1 -- A 7 tap gaussian using 2+1 texture fetches.
#if pattern == 1

// -- Gaussian filter --
// [ 2/9, 4/9, ] [ 1 , 2 , ]
// [ 4/9, 8/9, 4/9] = [ 2 , 4 , 2 ]
// [ , 2/9, 2/9] [ , 2 , 1 ]

float4 blur_ori = tex2D(s0, tex + float2(-px,py) / 3 * offset_bias); // North West
blur_ori += tex2D(s0, tex + float2(px,-py) / 3 * offset_bias); // South East

//blur_ori += tex2D(s0, tex + float2(px,py) / 3 * offset_bias); // North East
//blur_ori += tex2D(s0, tex + float2(-px,-py) / 3 * offset_bias); // South West

blur_ori /= 2; //Divide by the number of texture fetches

#endif

// -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches.
#if pattern == 2

// -- Gaussian filter --
// [ .25, .50, .25] [ 1 , 2 , 0 ]
// [ .50, 1, .50] = [ 2 , 4 , 2 ]
// [ .25, .50, .25] [ 0 , 2 , 1 ]

float4 blur_ori = tex2D(s0, tex + float2(-px,py) * 0.5 * offset_bias); // North West
blur_ori += tex2D(s0, tex + float2(px,-py) * 0.5 * offset_bias); // South East
blur_ori += tex2D(s0, tex + float2(px,py) * 0.5 * offset_bias); // North East
blur_ori += tex2D(s0, tex + float2(-px,-py) * 0.5 * offset_bias); // South West

blur_ori /= 4; //Divide by the number of texture fetches

#endif

// -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches.
#if pattern == 3

// -- Gaussian filter --
// [ , 4 , 6 , , ]
// [ ,16 ,24 ,16 , 4 ]
// [ 6 ,24 , ,24 , 6 ]
// [ 4 ,16 ,24 ,16 , ]
// [ , , 6 , 4 , ]

float4 blur_ori = tex2D(s0, tex + float2(-0.4*px,1.2*py) * offset_bias); // North North West
blur_ori += tex2D(s0, tex + float2(0.4*px,-1.2*py)* offset_bias); // South South East
blur_ori += tex2D(s0, tex + float2(1.2*px,0.4*py) * offset_bias); // East North East
blur_ori += tex2D(s0, tex + float2(-1.2*px,-0.4*py) * offset_bias); // West South West
blur_ori += ori; // Probably not needed. Only serves to lessen the effect.
blur_ori /= 5; //Divide by the number of texture fetches
#endif

// -- Calculate the sharpening --
float4 sharp = ori - blur_ori; //Subtracting the blurred image from the original image

// -- Adjust strength of the sharpening --
sharp = dot(sharp, sharp_strength_luma); //Calculate the luma and adjust the strength

// -- Clamping the maximum amount of sharpening to prevent halo artifacts --
sharp = clamp(sharp, -sharp_clamp, sharp_clamp); //TODO Try a curve function instead of a clamp

// -- Combining the values to get the final sharpened pixel --
float4 done = ori + sharp; // Add the sharpening to the original.

// .------------------------------------------------._Debugging and tweaking.-----------------------------------------------.

//For tweaking and debugging purposes you can show the sharpen effect or chroma.
//float4 done = (sharp*4) + float4(0.5,0.5,0.5,0); // Uncomment to visualize the strength of the sharpen (multiplied by 4 to see it better)

//done = ori.a; // Visualize the alpha
//done = 1.0 - ori.a; // Visualize the inverted alpha

// .-------------------------------------------------._Returning the output_.-----------------------------------------------.

return done;
}

It basically does the same thing, but with fewer instructions and the code looks much cleaner and is easier to read. There is also a new experimental 17-tap gaussian or at least it is a gaussian if my math is correct.

Also I corrected a bug in the fast version (pattern 1) where previously it moved the samples 0.5 (fixed version moves them 1/3) from center which worked but resulted in something more like a highpass sharpen than a gaussian.

JanWillem32
2nd February 2012, 17:52
Sorry I'm responding this late, this thread had already moved to page 2 before I noticed a response. I looked up the sampling parameters for D3D and DXGI. It appears that the Sample intrinsic (in both versions of the DX API) by defaults reserves pipelines on the shadercore to process anisotropic spatial filtering by default, and shaders themselves don't have indicators to indicate a lower requirement. The Load intrinsic (DXGI only) is handled by an entirely different pipeline, and can't be filtered. I didn't expect such a big difference in the methods for the basic Load and Sample on nearest neighbor. Maybe in a while I'll try to add optional bilinear filtering on custom pixel shader sampler stages for the DirectX 9 renderer I'm working on.
Your shader looks very promising. The debug section to visualize each section is very helpful, I use such mechanisms in rendering all the time. Just don't look too long at those rainbow colors while adjusting settings. :D The effect is of course, quite psychedelic, and can cover up the main intention for a shader's usage.
The methods seem pretty much correct. The only note I have is that mentioning the LAB colorspace is a bit wrong in this context. This shader only converts to Y'CbCr. That's also a luma-chroma system, but doesn't nearly have as much colorspace coverage or control as LAB or XYZ:
http://en.wikipedia.org/wiki/CIE_1931_color_space
http://en.wikipedia.org/wiki/Lab_color_space
http://en.wikipedia.org/wiki/File:Colorspace.png
(Although I must note that Y'CbCr is easier to handle than LAB. LAB is even more mathematically non-uniform than Y'CbCr, mostly because of a difficult gamma slope.)
Anyway, good luck with further developing.

leeperry
22nd November 2012, 10:44
Hi Jan, thanks for the scripts! Now that madVR supports them, this thread is well worth a bump :)

I can't see any script that would process a mirroring effect, wouldn't that be possible via a PS script? All I can see is flipping :o

And an artificial film grain script much like GrainFactory3() (http://avisynth.org/mediawiki/GrainFactory3) could also be really handy for low bitrate encodes.

:thanks:

burfadel
23rd November 2012, 23:22
I agree!

A nice effect that would be good as a shader is 'temporatal smoothing'. In FFDshow, under 'Blur & Noise Reduction', having everything unchecked except for 'Temporal smooth' (and of course, the box to actually activate the smoothing options), have it set to '1', and 'process color'.
'

leeperry
13th December 2012, 03:57
Hi Jan, I was wondering if you would have any plan to implement some sort of dynamic contrast stuff like Samsung's DNIE (http://forum.doom9.org/showpost.php?p=1600258&postcount=15433)?

It looks quite impressive on their TV's but it's neither defeatable or finetunable, and quite frankly they went quite overboard with the default settings....I guess it's meant to stun you in the shop but it basically makes everything look like a cell-shading cartoon = very funny for a few days, then it WILL get old after a while :o

They do it to compensate for the infamous 2K:1 native CR of their grossly overpriced TV's but the idea is good, it would only need to be finetunable I think. They allow several settings for their motion interpolation stuff(that looks quite good in "crisp" mode) so I dunno why they don't provide it for DNIE :rolleyes:

Besides, the best looking scalers in madVR require quite a lot of horsepower for 1080p and/or 60fps scaling so let's rock with the PS scripts while we're at it :D

I'd love to hear your thoughts on that matter, :thanks:

toniash
13th December 2012, 12:19
Besides, the best looking scalers in madVR require quite a lot of horsepower for 1080p and/or 60fps scaling so let's rock with the PS scripts while we're at it :D


PS scripts can be also very heavy on GPU

leeperry
13th December 2012, 16:22
Indeed, but atm anything cheaper than a GTX660 is a waste of money if you like it green so that leaves a lot of GPU power unused.....but I see that Jan has been silent for a while.

leeperry
28th December 2012, 19:49
so more ideas in case there'd be any bored PS script coder around: http://www.youtube.com/watch?v=rRf2aEsJaQE

pretty funky way to watch 4:3 content on a 16/9 display, would love to try it on my own James Brown Soul Train DVD's :devil:

leeperry
30th December 2012, 02:46
also, would that be hard to make a "negative" script? you've made all kinds of complicated scripts that have no real world use AFAICS, but simple stuff such as flipping/mirroring/negative just isn't there :(

CeeJay.dk
3rd January 2013, 16:37
also, would that be hard to make a "negative" script? you've made all kinds of complicated scripts that have no real world use AFAICS, but simple stuff such as flipping/mirroring/negative just isn't there :(

That would be the easiest thing in the world, but why would you want to see a negative of the screen?

Anyways :

/* --- Defining Constants --- */

sampler s0 : register(s0);

/* --- Negative --- */
/*
by Christian Cann Schuldt Jensen ~ CeeJay.dk

Inverts the color of the image, making it negative.
*/

float4 NegativePass( float4 colorInput )
{
return 1.0 - colorInput;
}

/* --- Main --- */

float4 main(float2 tex : TEXCOORD0) : COLOR {
float4 FinalColor = tex2D(s0, tex);

FinalColor = NegativePass(FinalColor);

return FinalColor;
}

EDIT : While testing the negative shader I made , I found that MPC-HC already has one. It's called Invert.
This is it's code :

sampler s0 : register(s0);

float4 main(float2 tex : TEXCOORD0) : COLOR {
float4 c0 = float4(1, 1, 1, 1) - tex2D(s0, tex);

return c0;
}

It does exactly the same. Subtracts the pixel color from 1.0

leeperry
4th January 2013, 02:10
sweeet, :thanks: a bunch!

well, PS scripts don't work in 8bit like ffdshow so I can use them without killing the PQ in mVR and I like to have troubleshooting scripts "just in case" ;)

I used to code Seka assembler on Amiga back in the days and I heard that coding PS scripts was great fun because you only had to care about the good side of coding, so I might document myself on how to write these at some point. If anything, I'd crave for a less agressive DNIE (http://forum.doom9.org/showpost.php?p=1600258&postcount=15433) :)

Dodgexander
31st January 2013, 15:32
When using these in MPC-HC. I get errors:

memory(203,11): warning X3571: pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you expect them
memory(155,9): error X5589: Invalid const register num: 32. Max allowed is 31.

leeperry
31st January 2013, 17:24
did you set them to PS 3.0? did you RTFM if any? :p

Dodgexander
1st February 2013, 13:54
did you set them to PS 3.0? did you RTFM if any? :p

The pixel shader was indeed the problem, for some reason when I set to Pixel Shader 3, it reverts back to 2 and I have to change back to 3 again for it to work!

The results here are truly amazing, now I just have to pick the best option and automate. Thanks a lot for the help.

Oh another question though, when I use the YCbCr-type sharpen complex test 2 scripts, my screen completely goes purple.

http://imageshack.us/scaled/thumb/255/testtpz.png (http://imageshack.us/photo/my-images/255/testtpz.png/)

leeperry
2nd February 2013, 03:33
told ya, SimHD is the usual commercial bs clueless companies brag about...they always promise a lot but actually end up delivering very little. Doom9's forum is where the party's at for supreme PQ =)

don't bother with YCbCr, you wanna use RGB scripts with madVR.

Dodgexander
3rd February 2013, 02:50
Doing these scripts reminds me of a while back following 8:13's post for post processing in FFdshow via Avisynth, the results back then were impressive and today, with the video card doing the work its even better, especially with low end cpu!

I wish however that someone would develop all this post processing into a decoder or renderer like ffdshow. It would be so much easier to set up.

Dodgexander
15th February 2013, 00:18
Is there an easier way to import all of these files to switch between them without having to copy and paste each text file into MPC-HC?

Also, I like the effect that the blur shader has, but can't use it with any of the sharpen, deband and denoise filters at the same time. Is there any way around this?

Also, what other shaders are people using on their SD material for best effects?

Finally, using Mad VR upscaling chroma and Luma already, how can i make sure none of the effects are conflicting?

leeperry
1st May 2013, 11:01
BTW, mVR currently doesn't align chroma properly for MPEG1 as shown here (http://forum.doom9.org/showpost.php?p=1622754&postcount=18186).

Would anyone be kind enough to write a PS script that would fix this please? :thanks:

Is there an easier way to import all of these files to switch between them without having to copy and paste each text file into MPC-HC?
Dunno about MPC but you can just put them all in the /PxShader/ subdirectory of PotP, et voilà: http://thumbnails104.imagebam.com/25196/7c8097251955360.jpg (http://www.imagebam.com/image/7c8097251955360)

You can also setup automatic profiles with different combinations of PS scripts depending on frame rate/resolution/codec/etc :)

XRyche
6th July 2013, 01:54
Is there any way that you would make a YCbCr r=2 or r=1, sharpen complex, deband, denoise and color controls for SD&HD video input shader at this late date? The r=4 shader is a little to taxing on my rig with out overclocking my video card for some 1200p content that could use some debanding.

JanWillem32
7th July 2013, 22:14
Sure, I still often write shaders. (Just most of them are not for video renderers.) What shader chain would you like to use? I can probably reduce some of the overhead, or use somewhat more lightweight methods to get what you want.

XRyche
8th July 2013, 06:34
I'm not that tech-savy or a video-phile so I am not quite sure what you're asking. If you mean the order of shaders I use (they are all yours btw :) ) they are as follows and in the following order; Pre-resize: RGB to Y'CbCr floating point, 4:2:0 to 4:2:2 Chroma Up-sampling, 4:2:2 Spline5 Chroma Up-Sampling floating point for Y'CbCr, one of your r=?, sharpen complex, deband, ? denoise and color controls for SD&HD video input, and lastly unsharp luma mask for SD&HD video (the black border compensation is very very nice :) ). I don't really use post-resize shaders often. Have never found a need for them with your shaders. What I think I'm looking for is your "r=?, sharpen complex, deband, ? denoise and color controls for SD&HD video input for Y'CbCr" shader using only 1 or 2 radial layered sharpening functions. I've used your linear gamma shaders before using only 1 or 2 radial layered sharpening with 1200p and that seem to work for me. I just don't like the Linear Gamma shaders because I get massive artifacts when denoiseing and I can see the outlines for the sharpening (I'm probably doing something wrong). I tried raising the GammaCompensation value but that seems to have a negative impact on the denoising and sharpening effects.

While I have your attention, would there be any perceivable benefit in 4:4:4 Chroma Up-Sampling and if there was would you be willing to write a Y'CbCr shader for it? I've taken a really strong appreciation for your Y'CbCr shaders compared to RGB. Colours are much more subtle and not as harsh when using RGB at least to me. I prefer your Video renderer/w Y'CbCr shaders over a certain other extremely popular renderer simply for this fact.

mhourousha
8th July 2013, 08:20
I wrote a Color Vibrance Shader for some GPU without 'digital vibrance' feature (Intel HD Graphic for example)

sampler s0 : register(s0);
float4 p0 : register(c0);
float4 p1 : register(c1);

float3 ColorVibrance(float3 rgb,float vibrance)
{

//--Convert RGB to HSL--
float maxvalue = max(rgb.r,rgb.g);
float minvalue = min(rgb.r,rgb.g);
maxvalue = max(rgb.b,maxvalue);
minvalue = min(rgb.b,minvalue);
float CValue = maxvalue-minvalue;
float3 hsl = float3(0.0,0.0,0.0);
hsl.z = 0.5f*(maxvalue+minvalue);
float tempf = 1.0f-abs(hsl.z*2.0f-1.0f);
if(CValue<0.0001f)
{
return rgb;
}
hsl.y = CValue/tempf;

//--Boost pixel's Saturation base on its original Saturation
hsl.y +=hsl.y*(1.0f-hsl.y)*vibrance;
//--Conver HSL back to RGB-
float CValue2 = hsl.y*tempf;
float mValue = hsl.z-0.5f*CValue2;
float3 BaseColor = float3(0.0f,0.0f,0.0f);
if(maxvalue-0.00001f <= rgb.r)
{
BaseColor.x = 1.0f;
hsl.x = (rgb.g-rgb.b)/CValue;
if(hsl.x<0.0f)
{
BaseColor.z = -hsl.x;
}
else
{
BaseColor.y = hsl.x;
}
}
else if(maxvalue-0.00001f <= rgb.g)
{
BaseColor.y = 1.0f;
hsl.x = (rgb.b-rgb.r)/CValue;
if(hsl.x<0.0f)
{
BaseColor.x = -hsl.x;
}
else
{
BaseColor.z = hsl.x;
}
}
else
{
BaseColor.z = 1.0f;
hsl.x = (rgb.r-rgb.g)/CValue;
if(hsl.x<0.0f)
{
BaseColor.y = -hsl.x;
}
else
{
BaseColor.x = hsl.x;
}
}
return float3(mValue,mValue,mValue)+float3(CValue2,CValue2,CValue2)*BaseColor;
}
float4 main(float2 tex : TEXCOORD0):Color0
{
float4 c0 = saturate(tex2D(s0, tex));
float vibrance = 0.5;
return float4(ColorVibrance(c0.xyz,vibrance),1.0);
}

PetitDragon
8th July 2013, 16:08
I'm not that tech-savy or a video-phile so I am not quite sure what you're asking. If you mean the order of shaders I use (they are all yours btw :) ) they are as follows and in the following order; Pre-resize: RGB to Y'CbCr floating point......

Could you tell us what version of Jan's test build you are using with these PS shaders?

JanWillem32
10th July 2013, 01:30
XRyche, do you actually need the chroma up-sampling shaders? They only work on AMD/ATi and Intel GPUs in the quality mode. For the performance mode, the default mixer up-sampling is used and for nVidia GPUs the chroma up-sampling can't be overridden unless you take out the VMR-9 or EVR mixer. If you do need them, which of the current types in the renderer do you like? The higher-order types from the pixel shader pack are somewhat faulty.
I can certainly mix the sharpen complex~ and the luma-type unsharp mask shaders, they pretty much act on the pixels in a similar fashion anyway.
Gamma linearization is still important for Y'CbCr to R'G'B' to RGB to XYZ stages. By default, the renderer I wrote takes good care of these steps in the quality mode. Letting external shaders do such a task is required when you set "Disable Initial Color Mixing Stages" for the renderer (which does give a lot of control over that stage, with nearly ideal efficiency).

mhourousha, this shader does seem interesting. A quick glance shows some minor things to possibly improve, though.
First of all, unlike C, HLSL does not take 'F' or 'f' as a suffix for single precision. Single precision is the default, and double precision takes an 'l' or 'L' suffix.
Secondly, for what reason is saturation used? Various rendering stages for video playback and other HDR imaging produce valid output beyond the 0 minimum and 1 maximum. Other than some anti-aliasing methods that have to deal with the spatial problems of multi-sampling pixels into one output, I've never seen valid reasons to actively saturate colors.
Third, some parts could improve by using shuffle masks, such as: "mValue.rrr" or just "mValue" instead of "float3(mValue,mValue,mValue)" and "ColorVibrance(c0.xyz,vibrance).rgbb" instead of "float4(ColorVibrance(c0.xyz,vibrance),1.0)".
Fourth, why did you use "0.00001f" instead of a true floating-point epsilon? On top of that, why did you use such a small value at all? The only reason I can see is because "hsl.y = CValue/tempf;" could possibly do a division by zero. For that one changing the previous comparison to "CValue <= 0." would suffice though.

mhourousha
10th July 2013, 06:51
JanWillem32:
about the saturate,some renderer(MadVR for example),doesn't clamp the color between[0,1] for the surface used as source by the shader.so artifact would occur as I don't saturate the 'c0'
about shuffle mask,it's my habit :D ,I think the shader compiler would optimize it.
about the 0.00001f,first, it's not good to do a 'equal' comparision between float values.second,I didn't trust gpu on doing division by very small value.:p

XRyche
10th July 2013, 08:58
XRyche, do you actually need the chroma up-sampling shaders? They only work on AMD/ATi and Intel GPUs in the quality mode. For the performance mode, the default mixer up-sampling is used and for nVidia GPUs the chroma up-sampling can't be overridden unless you take out the VMR-9 or EVR mixer. If you do need them, which of the current types in the renderer do you like? The higher-order types from the pixel shader pack are somewhat faulty.
I can certainly mix the sharpen complex~ and the luma-type unsharp mask shaders, they pretty much act on the pixels in a similar fashion anyway.
Gamma linearization is still important for Y'CbCr to R'G'B' to RGB to XYZ stages. By default, the renderer I wrote takes good care of these steps in the quality mode. Letting external shaders do such a task is required when you set "Disable Initial Color Mixing Stages" for the renderer (which does give a lot of control over that stage, with nearly ideal efficiency).

Wow, I know enough just to make myself look like an idiot :rolleyes: .As a matter of fact it is the higher order types from your pixel shader pack that give me issues. I should have made that clear....oops again. I understand now that the chroma up-sampling shaders are unnecessary for my GPU (Nvidia), I checked myself and I didn't see any change at all with or without them. I incorrectly assumed that they worked without really bothering to compare. Am I correct in assuming the the RGB to Y'CbCr conversion shader does exactly that (I do definitely see a difference, if not....it's off to the optometrist I go :) .)?

As far as the sharpen complex and luma unsharpen mask shaders i would say "Yes, please". When I use the Luma unsharpen mask shader it has a tendency to clean up some of my old tv card rips without having to use excessive denoising. I assumed the "black border compensation" has something to do with that.

Also if you could write a r=1 and an r=2 "sharpen complex, deband, ? denoise and color controls for SD&HD video input" Y'CbCr (I know they are "test" shaders but they appear to do everything they say they do without issue for me). I use your higher order ones for alot of SD and 720p content anyway.

Thanks for setting me straight on the chroma upsampling issue. I had no idea EVR had that kind of limitation.

JanWillem32
10th July 2013, 10:39
XRyche, the RGB to Y'CbCr conversion shader is fairly basic. I assume you mean the chroma up-sampling shaders? These will distort the chroma if the values were altered before. Sharp chroma borders such as red on black and blue on black will have the worst artifacts.
I'll see what I can write today and tomorrow. Implementing this chain as three passes of pixel shaders should be easy enough.

mhourousha, not only MadVR preserves output beyond the 0 minimum and 1 maximum. It's standard in all quality rendering. Most video filters are expected to be able to take full floating point range inputs, correctly process everything and then output. That said, what artifacts do you expect? Of the entire set of pixel shaders in the pixel shader pack and all other shaders I've ever written except for the stages for a type of anti-aliasing, I never had to use saturation on colors at all. (Saturating and clamping on vertices is pretty common though.)
The ".rgbb" shuffle at the end is mostly a trick to prevent two write instructions to the output register (one for the three color channels and one for the the alpha output color channel). The other shuffles can be optimized by the compiler indeed.
In my honest opinion, all those teachers that still teach "do not use direct comparisons with floating point logic" and don't bother with actually explaining machine epsilon and relative error accumulation by instructions should get a whipping.
In this case it's about a division. For the right-hand operand in floating-point division, there are 5 special cases: -infinity, infinity, -0, 0 and not-a-number inputs. NaN is not an issue in this case and division by infinity will work as expected. Only straight division by exactly -0 and 0 will produce a NaN, -infinity or infinity, depending on the left-hand operand.
Handling small numbers on a GPU has not been an issue ever since the introduction of the programmable pipeline. It's actually CPUs that had issues with small numbers for up until recent models. Intel even introduced flags on x86 CPUs to allow flushing denormal values to zero and assume denormals as zero (not applied by default, as it breaks IEEE and most programming language standards). Most CPUs in use today do not have native denormal support in in their floating-point processing units. Whenever a denormal is detected in such a CPU, an interrupt is emitted, the FPU is put offline and the calculation with the denormal is done by emulation. Such operations can cost over a thousand clock ticks. Full-speed single precision floating point denormal handling is important (and costly in terms of transistor counts) on GPUs. GPUs don't have any other logic on board to emulate any instructions in the first place. On top of that, slowing down certain instructions in one core will pause all other grouped cores in a GPU (the curse of massive parallelism, which does apply on any branching code).
In terms of accuracy of divisions, I looked up the 'rcp' instruction (hlsl will generally not compile to straight division, but rather use fast reciprocal and multiply), the documentation is what I expected it would be: http://msdn.microsoft.com/en-us/library/windows/desktop/bb147315%28v=vs.85%29.aspx .
There are no issues with handling small numbers on a GPU, as long as the numbers don't require such a large exponent or mantissa that only double precision or even greater will suffice for calculations.
In regards to floating-point equality evaluations, any floating-point number compared to iself for equality will yield true, except for NaNs. Floating-point numbers do get altered by arithmetic instructions, which accumulate relative error that you might have to compensate for. However, the only instruction I see before the last set of comparisons to "rgb" and "maxvalue" is 'max'. That is a flat branching instruction, not an arithmetic type. No relative error is accumulated, so the epsilon on these comparisons is useless.

mhourousha
10th July 2013, 13:43
JanWillem32,thx for reply
about saturation:because RGB<->HSL is not a linear transform,it required lightness between[0,1],value beyond this range will cause artifact.http://en.wikipedia.org/wiki/HSL_color_space
about shader compiler optim:in fact,the token-assembly shader language(the asm shader in windows platform's D3D)is not 1 to 1 mapping to HW instruction. .rgbb will save a token-asm instruction like ‘mov oC0.w,c0‘ indeed.but if you look at the HW assembly(use Tool like ShaderAnalyzer),two method will cost the same clock cycle under most case.and if use .rgbb,it assumed that the alpha channel will not be used in future,it's not a always-safe trick,right? oh I see, I should use 'return float4(ColorVibrance(c0.xyz,vibrance),c0.w);'instead of'return float4(ColorVibrance(c0.xyz,vibrance),1.0);'
about floating point,for recent GPU,you are right.but some old GPU,not implement IEEE standard strictly,like ATI R300-R400's fp24 internal precision,and I'm afraid some shader compiler's aggressive optimization may use fp16 instead of fp32 (for Old NVidia card).so I use the epsilon for safe, it only cause a very little performance-hit.

XRyche
11th July 2013, 16:51
XRyche, the RGB to Y'CbCr conversion shader is fairly basic. I assume you mean the chroma up-sampling shaders? These will distort the chroma if the values were altered before. Sharp chroma borders such as red on black and blue on black will have the worst artifacts.
I'll see what I can write today and tomorrow. Implementing this chain as three passes of pixel shaders should be easy enough.



No, I didn't mean the chroma up-sampling shaders. I already understand now that I don't need them since I have an Nvidia GPU. I meant that I wanted you to create 2 "sharpen complex, deband, denoise and color controls for SD&HD video input". One with 2 radial sharpening levels and one with 1 radial sharpening level. Similar to what you have for the Linear RGB sharpen complex, deband and denoise shaders in your Video pixel shader pack. I happen to prefer Y'CbCr to RGB and I would like to use the "RGB to Y'CbCr for SD&HD video input for floating point surfaces" shader in conjuction with the Y'CbCr "sharpen complex, deband, denoise and color controls for SD&HD video input" shaders with all my content. This includes some 1200p content which is too much for my system to use with your Y'CbCr "r=4, sharpen complex, deband, medium denoise and color controls for SD&HD video input" shader. :thanks:

edit: I don't mean to sound demanding, if that's how it sounds.

JanWillem32
13th July 2013, 22:24
XRyche, I'm still experimenting a bit with some shader stages. The shaders are not that hard to combine, but getting a combination of good performance and amiable effects isn't easy. On top of that, these are pretty much the most complex shaders I've written for processing video. I'm pretty sure I should simplify some parts, but I'll just have to try some things and hope the effect gets better.

mhourousha, I took some time to analyze what kind of effect you were trying to apply. I saw that it only increases colorfulness. The bulk of the code in your shader is the rather involved process of RGB to HSL conversion and back again. From what I could make up of the articles about the HSV and HSL color models is that they are RGB representations. They equally suffer the same problem as RGB models: without values encoded outside the nominal color interval, it is impossible to represent the gamut of human vision. http://en.wikipedia.org/wiki/CIE_1931_color_space
(Note that even when rendering in a color space that does accommodate the gamut of human vision, saturation isn't used. Various filtering steps may just shift color data in and out of visible and invisible areas of the color space. That just happens when rendering. When dealing with a renderer you have to design things that can deal with ranges up to 1 as up to 100 just as easily in most stages.)
HSV and HSL mostly seem to be convenient when doing or comparing shifts in the hue, which is a more complicated matter in RGB models. (It's not that hard if you can handle matrix transforms. I added a few shaders as an example.)
I already had a colorfulness shader, but I didn't mind making another type for the occasion. Note that you can do a lot more complex transforms than one simple multiply in the line "s1.rgb = (s1.rgb-inptot)*colorfulness+inptot;".
I saved quite a lot of instructions on not doing the complex color space transforms. In terms of (expensive) branching, I only had to use one to prevent a division by zero.
You specified that you wanted to cater to the 16-bit internal precision of the Nvidia NV30, NV31 and NV34 models introduced ten years ago (and were never DirectX 9.0 compliant because of the precision issue).
http://en.wikipedia.org/wiki/Machine_epsilon
The precision of the 16-bit floating point type is rather bad, its machine epsilon is 0.0009765625. The value you used was 0.0001. That value covers 0.2048 bits of maximum precision loss, assuming the interval [.5, 1).
The precision of the 24-bit floating point type is a lot better, its machine epsilon is 0.0000152587890625. The value 0.0001 covers 13.1072 bits of maximum precision loss, assuming the interval [.5, 1).
For the execution of this shader that all doesn't matter though: of the cases where applying epsilon was assumed useful, it actually was not. None of the cases here have to do deal with precision loss due to the specific limited amount of of mantissa bits.
Hardware assembly execution speed and amount of D3D asm instructions are not tied 1:1 indeed. Modern processor architectures are superscalar. Everything that can be simultaneously executed without stalling will generally be executed at the same time as other instructions. Note that the rules vary per architecture. The D3D asm instruction count is still a good indication of how fast a shader will run on average.
In regards the the fourth component on the output of a pixel shader, I can be clear on that. The performance mode uses X8R8G8B8 to store color, thus not saving the fourth component at all. The quality modes use A16B16G16R16F, A16B16G16R16 and A32B32G32R32F. These can store the fourth component. If you want to design a specific chain of multiple shaders for some effect, you are welcome to put data in the fourth component for every pixel. However, none of the renderer components themselves will ever use that channel. I advise to treat the fourth component as discarded for most pixel shaders.
Other renderer stages that handle textures with valid alpha do require processing the fourth component. For blending the OSD and subtitles two special pixel shaders are used in combination with alpha blending. The renderer has always been this way in regards to this aspect, I don't expect changes either.

Sample shaders (the XYZ types can only properly function with the renderer in quality mode):// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// very basic colorfulness control

#define colorfulness 1.5// default is one, this should not be zero

sampler s0 : register(s0);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = tex2D(s0, tex);
float inptot = dot(1/3., s1.rgb);// component average

[branch] if (inptot) {// prevent division by zero
s1.rgb = (s1.rgb-inptot)*colorfulness+inptot;
float intermtot = dot(1/3., s1.rgb);
s1.rgb *= inptot;
s1.rgb /= intermtot;}
return s1;
}



// colorfulness control for XYZ rendering

// white point in xyY, default is TV-type D65 {.3127, .3290, 1}, the most basic is E {1/3., 1/3., 1}
#define wpx .3127
#define wpy .3290// this cannot be zero

#define colorfulness 1.5// default is one, this should not be zero

sampler s0 : register(s0);
static const float wpyr = 1./wpy;
static const float wpX = wpx*wpyr;
static const float wpZ = wpyr-wpX-1.;
static const float3 wpXYZ = {wpX, 1, wpZ};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = tex2D(s0, tex);
float inptot = dot(1/3., s1.rgb);// component average

[branch] if (inptot) {// prevent division by zero
s1.rgb /= wpXYZ;// adapt white point
s1.rgb = (s1.rgb-inptot)*colorfulness+inptot;
float intermtot = dot(1/3., s1.rgb);
s1.rgb *= inptot;
s1.rgb /= intermtot;
s1.rgb *= wpXYZ;}// revert white point adaptation
return s1;
}



// hue shift for XYZ rendering

// white point in xyY, default is TV-type D65 {.3127, .3290, 1}, the most basic is E {1/3., 1/3., 1}
#define wpx .3127
#define wpy .3290// this cannot be zero

#define hue 180// in degrees, default is zero

sampler s0 : register(s0);
static const float wpyr = 1./wpy;
static const float wpX = wpx*wpyr;
static const float wpZ = wpyr-wpX-1.;
static const float3 wpXYZ = {wpX, 1, wpZ};
static const float huecos = cos(radians(hue));
static const float huesin = sin(radians(hue));
static const float huecosp = 1/3.-huecos/3.;
static const float huesinp = sqrt(1/3.)*huesin;
static const float huebase = huecosp+huecos;
static const float huedera = huecosp+huesinp;
static const float hueders = huecosp-huesinp;
static const float3x3 hueshiftmat = {
huebase, huedera, hueders,
hueders, huebase, huedera,
huedera, hueders, huebase};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = tex2D(s0, tex);
s1.rgb /= wpXYZ;// adapt white point
s1.rgb = mul(s1.rgb, hueshiftmat);
s1.rgb *= wpXYZ;// revert white point adaptation
return s1;
}



// variable hue shift for XYZ rendering

// white point in xyY, default is TV-type D65 {.3127, .3290, 1}, the most basic is E {1/3., 1/3., 1}
#define wpx .3127
#define wpy .3290// this cannot be zero

#define hue c0.w// in radians, default is zero

sampler s0 : register(s0);
float4 c0 : register(c0);
static const float wpyr = 1./wpy;
static const float wpX = wpx*wpyr;
static const float wpZ = wpyr-wpX-1.;
static const float3 wpXYZ = {wpX, 1, wpZ};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float huecos = cos(hue);
float huesin = sin(hue);
float huecosp = 1/3.-huecos/3.;
float huesinp = sqrt(1/3.)*huesin;
float huebase = huecosp+huecos;
float huedera = huecosp+huesinp;
float hueders = huecosp-huesinp;
float3x3 hueshiftmat = {
huebase, huedera, hueders,
hueders, huebase, huedera,
huedera, hueders, huebase};

float4 s1 = tex2D(s0, tex);
s1.rgb /= wpXYZ;// adapt white point
s1.rgb = mul(s1.rgb, hueshiftmat);
s1.rgb *= wpXYZ;// revert white point adaptation
return s1;
}

// colorfulness control for XYZ rendering on 16-bit integer surfaces

// white point in xyY, default is TV-type D65 {.3127, .3290, 1}, the most basic is E {1/3., 1/3., 1}
#define wpx .3127
#define wpy .3290// this cannot be zero

#define colorfulness 1.5// default is one, this should not be zero

sampler s0 : register(s0);
static const float wpyr = 1./wpy;
static const float wpX = wpx*wpyr;
static const float wpZ = wpyr-wpX-1.;
static const float3 wpXYZ = {wpX, 1, wpZ};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = tex2D(s0, tex);
s1.rgb -= 16384/65535.;// remove input interval [16384/65535, 49151/65535] offset to black point
float inptot = dot(1/3., s1.rgb);// component average

[branch] if (inptot) {// prevent division by zero
s1.rgb /= wpXYZ;// adapt white point
s1.rgb = (s1.rgb-inptot)*colorfulness+inptot;
float intermtot = dot(1/3., s1.rgb);
s1.rgb *= inptot;
s1.rgb /= intermtot;
s1.rgb *= wpXYZ;}// revert white point adaptation
s1.rgb += 16384/65535.;// re-apply black point offset
return s1;
}



// hue shift for XYZ rendering on 16-bit integer surfaces

// white point in xyY, default is TV-type D65 {.3127, .3290, 1}, the most basic is E {1/3., 1/3., 1}
#define wpx .3127
#define wpy .3290// this cannot be zero

#define hue 180// in degrees, default is zero

sampler s0 : register(s0);
static const float wpyr = 1./wpy;
static const float wpX = wpx*wpyr;
static const float wpZ = wpyr-wpX-1.;
static const float3 wpXYZ = {wpX, 1, wpZ};
static const float huecos = cos(radians(hue));
static const float huesin = sin(radians(hue));
static const float huecosp = 1/3.-huecos/3.;
static const float huesinp = sqrt(1/3.)*huesin;
static const float huebase = huecosp+huecos;
static const float huedera = huecosp+huesinp;
static const float hueders = huecosp-huesinp;
static const float3x3 hueshiftmat = {
huebase, huedera, hueders,
hueders, huebase, huedera,
huedera, hueders, huebase};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = tex2D(s0, tex);
s1.rgb -= 16384/65535.;// remove input interval [16384/65535, 49151/65535] offset to black point
s1.rgb /= wpXYZ;// adapt white point
s1.rgb = mul(s1.rgb, hueshiftmat);
s1.rgb *= wpXYZ;// revert white point adaptation
s1.rgb += 16384/65535.;// re-apply black point offset
return s1;
}



// variable hue shift for XYZ rendering on 16-bit integer surfaces

// white point in xyY, default is TV-type D65 {.3127, .3290, 1}, the most basic is E {1/3., 1/3., 1}
#define wpx .3127
#define wpy .3290// this cannot be zero

#define hue c0.w// in radians, default is zero

sampler s0 : register(s0);
float4 c0 : register(c0);
static const float wpyr = 1./wpy;
static const float wpX = wpx*wpyr;
static const float wpZ = wpyr-wpX-1.;
static const float3 wpXYZ = {wpX, 1, wpZ};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float huesin, huecos;
sincos(hue, huesin, huecos);
float huecosp = 1/3.-huecos/3.;
float huesinp = sqrt(1/3.)*huesin;
float huebase = huecosp+huecos;
float huedera = huecosp+huesinp;
float hueders = huecosp-huesinp;
float3x3 hueshiftmat = {
huebase, huedera, hueders,
hueders, huebase, huedera,
huedera, hueders, huebase};

float4 s1 = tex2D(s0, tex);
s1.rgb -= 16384/65535.;// remove input interval [16384/65535, 49151/65535] offset to black point
s1.rgb /= wpXYZ;// adapt white point
s1.rgb = mul(s1.rgb, hueshiftmat);
s1.rgb *= wpXYZ;// revert white point adaptation
s1.rgb += 16384/65535.;// re-apply black point offset
return s1;
}

detmek
14th July 2013, 10:05
I am using one or two shaders for small corections during playback, usually LumaSharpen or Sharpen Complex and Vibrance for anime. But sometimes video has a banding, usually my old encodes with denoised with FFT3DFilter.

Is there a pure deband shader that I can use to replace FFDShow Deband filter?

JanWillem32
16th July 2013, 18:58
The pure debanding shaders I tried were terrible. For the limit-based types, the worst cases were borders (even some pretty sharp ones). If the transition pixels on borders get blurred without compensating for the borders, aliasing occurs. For the gradual types, the main problem was blurring of pretty much everything.
So, I tried to use a gradual type, limit it, but additionally adapt a typical unsharp mask sharpening effect to to prevent some of the visible artifacts. For these adaptive shaders, the sharpening can be made stronger to accentuate contrast (without making banding and noise worse like other sharpen effects). I personally don't care about the sharpening effect, as I don't like seeing the sharpening halos at all. Though I know that if I set it too low or off, the other artifacts will be visible.
Every shader I wrote claiming to be able to deband and denoise has a notice on how to disable the sharpening effect. (Though I'm not sure how effective r=1 and r=2 types can be at debanding and denoising.) For the larger types, the sharpen factor can even be set for every layer.
In the mean time, I wrote a multi-pass sharpen, deband, denoise and color controls filter that should be better in terms of performance, while still doing a reasonably good job at debanding larger areas (the most costly part, as it requires a lot of pixels). If wanted, I can share it, but it's not quite finished yet.

PetitDragon
17th July 2013, 00:37
.... If wanted, I can share it, but it's not quite finished yet.

Yes please. We need a new shader pack for XYZ rendering.
:script::thanks:

turbojet
17th July 2013, 20:24
F3kdb has set my bar really high for debanding but I'm always interested in trying new methods. Will it be separate from sharpener, denoising and color controls?

JanWillem32 would you have interest writing an f3kdb shader? Developer of the avisynth plugin mentioned this a few months ago: http://forum.doom9.org/showthread.php?p=1621484#post1621484

jerrymh
23rd July 2013, 21:32
Where a can find a shader to put scanlines or crt grille on screen.

detmek
23rd July 2013, 22:32
Sure. I will be interested to try it. Its easier to use shader then loading FFDShow RAW filter.

JanWillem32
25th July 2013, 02:34
About the f3kdb shader, I'm quite interested. There's a limit to what I can do, though. Shaders work very differently compared to many other graphics filters. In most cases, translating to shaders is rather hard. I'll just have to try and be creative. It may just as well be easier than the combination effect shader chain I'm trying to write for XRyche. Where do I start?

jerrymh, that kind of effect is easy. I made this effect two-pass. If you want something more specific (such as a better quality lowpass), I can change a few parts. Depending on the input/output resolution ratio, you might need to blur a bit more or less.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// horizontal blur

sampler s0 : register(s0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
return (tex2D(s0, tex+float2(-3.*c1, 0))+tex2D(s0, tex+float2(-2.*c1, 0))+tex2D(s0, tex+float2(-c1, 0))+tex2D(s0, tex)+tex2D(s0, tex+float2(c1, 0))+tex2D(s0, tex+float2(2.*c1, 0))+tex2D(s0, tex+float2(3.*c1, 0)))/7.;// blur and output
}



// old CRT scan lines

#define scanlines 480// 480 for NTSC, 576 for PAL/SECAM, fractions, either decimal or not are allowed
#define gamma 1// higher is brighter, fractions, either decimal or not are allowed

sampler s0 : register(s0);
float2 c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = (tex2D(s0, tex+float2(0, -3.*c1.y))+tex2D(s0, tex+float2(0, -2.*c1.y))+tex2D(s0, tex+float2(0, -c1.y))+tex2D(s0, tex)+tex2D(s0, tex+float2(0, c1.y))+tex2D(s0, tex+float2(0, 2.*c1.y))+tex2D(s0, tex+float2(0, 3.*c1.y)))/7.;// blur input

float br = 1.-pow(abs(frac(abs(tex.y*scanlines-.5*scanlines))*2.-1.), gamma);// generate scan lines
return s1*br;// modulate brightness and output
}



// old CRT scan lines for XYZ rendering on 16-bit integer surfaces

#define scanlines 480// 480 for NTSC, 576 for PAL/SECAM, fractions, either decimal or not are allowed
#define gamma 1// higher is brighter, fractions, either decimal or not are allowed

sampler s0 : register(s0);
float2 c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = (tex2D(s0, tex+float2(0, -3.*c1.y))+tex2D(s0, tex+float2(0, -2.*c1.y))+tex2D(s0, tex+float2(0, -c1.y))+tex2D(s0, tex)+tex2D(s0, tex+float2(0, c1.y))+tex2D(s0, tex+float2(0, 2.*c1.y))+tex2D(s0, tex+float2(0, 3.*c1.y)))/7.;// blur input

float br = 1.-pow(abs(frac(abs(tex.y*scanlines-.5*scanlines))*2.-1.), gamma);// generate scan lines
return (s1-16384/65535.)*br+16384/65535.;// modulate brightness and output
}

turbojet
25th July 2013, 06:10
About the f3kdb shader, I'm quite interested. There's a limit to what I can do, though. Shaders work very differently compared to many other graphics filters. In most cases, translating to shaders is rather hard. I'll just have to try and be creative. It may just as well be easier than the combination effect shader chain I'm trying to write for XRyche. Where do I start?


Maybe messaging SAPikachu, the developer of f3kdb.dll he was open to helping in the message linked earlier. I have almost no programming experience so couldn't be of help.

XRyche
27th July 2013, 04:47
JanWillem32, First off.....Thank You for working on the hybrid shaders I've requested. I doubt if I would be able to find anyone else so willing to do that. Second, I have been doing some experimenting with different methods for cleaning up the image quality on a lot of my old XVID/DIVX/AVI files and it seems that they benefit more from deblocking (ffdshows raw filter mplayer deblocking) than denoising. I suppose since most of the files are old vhs to avi tv rips and old tvcard rips that makes sense. Anyways, would you be open to possibly doing an adjustable deblocking shader? I've read that ATI used to (I don't know if they still do) use it's shader core to do deblocking so I assume (whether correctly or not) it's possible to do it with an HLSL script. I don't have a clue what the math involved would be like so if you can't it's understandable.

turbojet
27th July 2013, 06:34
MPEG4 ASP is notorious for banding (could be mistaken for blocks on flat surfaces and faces) are you sure it's not banding?

f3kdb is a must for me with ASP much less so for any decent AVC encode or MPEG2. Have you tried it through ffdshow's avisynth interface? Make sure to use setmemorymax(128 or more) to stop the leakage.

jerrymh
28th July 2013, 05:09
About the f3kdb shader, I'm quite interested. There's a limit to what I can do, though. Shaders work very differently compared to many other graphics filters. In most cases, translating to shaders is rather hard. I'll just have to try and be creative. It may just as well be easier than the combination effect shader chain I'm trying to write for XRyche. Where do I start?

jerrymh, that kind of effect is easy. I made this effect two-pass. If you want something more specific (such as a better quality lowpass), I can change a few parts. Depending on the input/output resolution ratio, you might need to blur a bit more or less.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// horizontal blur

sampler s0 : register(s0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
return (tex2D(s0, tex+float2(-3.*c1, 0))+tex2D(s0, tex+float2(-2.*c1, 0))+tex2D(s0, tex+float2(-c1, 0))+tex2D(s0, tex)+tex2D(s0, tex+float2(c1, 0))+tex2D(s0, tex+float2(2.*c1, 0))+tex2D(s0, tex+float2(3.*c1, 0)))/7.;// blur and output
}



// old CRT scan lines

#define scanlines 480// 480 for NTSC, 576 for PAL/SECAM, fractions, either decimal or not are allowed
#define gamma 1// higher is brighter, fractions, either decimal or not are allowed

sampler s0 : register(s0);
float2 c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = (tex2D(s0, tex+float2(0, -3.*c1.y))+tex2D(s0, tex+float2(0, -2.*c1.y))+tex2D(s0, tex+float2(0, -c1.y))+tex2D(s0, tex)+tex2D(s0, tex+float2(0, c1.y))+tex2D(s0, tex+float2(0, 2.*c1.y))+tex2D(s0, tex+float2(0, 3.*c1.y)))/7.;// blur input

float br = 1.-pow(abs(frac(abs(tex.y*scanlines-.5*scanlines))*2.-1.), gamma);// generate scan lines
return s1*br;// modulate brightness and output
}



// old CRT scan lines for XYZ rendering on 16-bit integer surfaces

#define scanlines 480// 480 for NTSC, 576 for PAL/SECAM, fractions, either decimal or not are allowed
#define gamma 1// higher is brighter, fractions, either decimal or not are allowed

sampler s0 : register(s0);
float2 c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = (tex2D(s0, tex+float2(0, -3.*c1.y))+tex2D(s0, tex+float2(0, -2.*c1.y))+tex2D(s0, tex+float2(0, -c1.y))+tex2D(s0, tex)+tex2D(s0, tex+float2(0, c1.y))+tex2D(s0, tex+float2(0, 2.*c1.y))+tex2D(s0, tex+float2(0, 3.*c1.y)))/7.;// blur input

float br = 1.-pow(abs(frac(abs(tex.y*scanlines-.5*scanlines))*2.-1.), gamma);// generate scan lines
return (s1-16384/65535.)*br+16384/65535.;// modulate brightness and output
}

Thank you very much, :thanks::thanks:

How about a aperture grille like this on Final burn alpha, it feels like a real old crt, or LG plasma


http://img10.imageshack.us/img10/4519/6qhx.jpg

Or a scanlines at 95%

XRyche
28th July 2013, 08:19
@turbojet...Yes there is some banding but some of JanWillem32's shaders+his modified EVR-CP already help with that (as well as madVR all but eliminating banding) but blocking is still there without using fddshow's raw filter. Not that the raw filter is bad I just would like to eliminate it from my playback chain. If JanWillem32 can kindly make a deblocking shader that does as good of a job or better as the raw filter I would much rather use that.

Most of my problem video files are from old vhs recordings of TV shows converted to .avi's as well as some TIVO-type files and early PC TV card recordings so blocking is kind of a given as well as massive banding ;) . Considering that madVR doesn't do deblocking (it actually accentuates the blocking on some of my files) using madVR for these is sort of a no no without the raw filter or a shader script (one the madVR will not neuter because of gamma manipulation or such).

JanWillem32
28th July 2013, 14:17
Deblocking is mostly decoder territory. Many video codecs don't use the typical macroblocks at all. For those that do, you need the general blocking info for the luma, chroma and interlacing to deal with it. For h.264 (and some newer codecs) organized (de)blocking is mandatory for both encoder and decoder. The custom shader stages of the video renderer are a bit late in the rendering chain to properly work on blocking and such. I'm not sure if I can write a normal shader that can help with deblocking.

jerrymh, that picture mostly shows hand-drawn pixel art. No decent video will convert nicely to high contrast, low quantization images like that. I can approximate the effect by combining a few techniques, but note that posterization is a really messy effect (even in common 8-bit video and worst of all, it's everywhere).
It's a two-pass shader chain again. The warning for "should be divisible by 4" isn't too strict, the few artifacts are hard to see. For common resolutions such as 720- and 1080-line systems I can also adapt special shaders to compensate for this issue. I can also try to boost some of the contrast or colorfulness before posterization as well, but I didn't see much improvement with those effects enabled on the samples I used.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// horizontal 4-pixel averaging
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 4

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float pos = (trunc(tex.x*c0*.25)+.125)*c1*4.;// calculate the left positon of the current set of pixels
return (tex2D(s0, float2(pos, tex.y))+tex2D(s0, float2(pos+c1, tex.y))+tex2D(s0, float2(pos+2*c1, tex.y))+tex2D(s0, float2(pos+3*c1, tex.y)))*.25;// blur and output
}



// vertical 4-pixel averaging, dithering, posterizing and old CRT scan lines
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 4

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.03125, .03125, .25);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.125)*c1.y*4.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y)))*.25;// blur input
#if posterizedegamma
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*br;// modulate brightness and output
#else
s1 = round(s1*quantize+dithers);// dither and posterize
return s1*(br*quantizer);// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// vertical 4-pixel averaging, dithering, posterizing and old CRT scan lines for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 4

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.03125, .03125, .25);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.125)*c1.y*4.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y)))*.25;// blur input
#if posterizedegamma
s1 = s1*65535/32767.-16384/32767.;
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*(br*32767/65535.)+16384/65535.;// modulate brightness and output
#else
s1 = round((s1*65535/32767.-16384/32767.)*quantize+dithers);// dither and posterize
return s1*(br*quantizer*32767/65535.)+16384/65535.;// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// horizontal 5-pixel averaging
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 5

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float pos = (trunc(tex.x*c0*.2)+.1)*c1*5.;// calculate the left positon of the current set of pixels
return (tex2D(s0, float2(pos, tex.y))+tex2D(s0, float2(pos+c1, tex.y))+tex2D(s0, float2(pos+2*c1, tex.y))+tex2D(s0, float2(pos+3*c1, tex.y))+tex2D(s0, float2(pos+4*c1, tex.y)))*.2;// blur and output
}



// vertical 5-pixel averaging, dithering, posterizing and old CRT scan lines
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 5

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.025, .025, .2);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.1)*c1.y*5.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y)))*.2;// blur input
#if posterizedegamma
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*br;// modulate brightness and output
#else
s1 = round(s1*quantize+dithers);// dither and posterize
return s1*(br*quantizer);// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// vertical 5-pixel averaging, dithering, posterizing and old CRT scan lines for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 5

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.025, .025, .2);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.1)*c1.y*5.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y)))*.2;// blur input
#if posterizedegamma
s1 = s1*65535/32767.-16384/32767.;
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*(br*32767/65535.)+16384/65535.;// modulate brightness and output
#else
s1 = round((s1*65535/32767.-16384/32767.)*quantize+dithers);// dither and posterize
return s1*(br*quantizer*32767/65535.)+16384/65535.;// shrink interval back to normal after posterization, modulate brightness and output
#endif
}

jerrymh
28th July 2013, 22:35
Deblocking is mostly decoder territory. Many video codecs don't use the typical macroblocks at all. For those that do, you need the general blocking info for the luma, chroma and interlacing to deal with it. For h.264 (and some newer codecs) organized (de)blocking is mandatory for both encoder and decoder. The custom shader stages of the video renderer are a bit late in the rendering chain to properly work on blocking and such. I'm not sure if I can write a normal shader that can help with deblocking.

jerrymh, that picture mostly shows hand-drawn pixel art. No decent video will convert nicely to high contrast, low quantization images like that. I can approximate the effect by combining a few techniques, but note that posterization is a really messy effect (even in common 8-bit video and worst of all, it's everywhere).
It's a two-pass shader chain again. The warning for "should be divisible by 4" isn't too strict, the few artifacts are hard to see. For common resolutions such as 720- and 1080-line systems I can also adapt special shaders to compensate for this issue. I can also try to boost some of the contrast or colorfulness before posterization as well, but I didn't see much improvement with those effects enabled on the samples I used.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// horizontal 4-pixel averaging
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 4

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float pos = (trunc(tex.x*c0*.25)+.125)*c1*4.;// calculate the left positon of the current set of pixels
return (tex2D(s0, float2(pos, tex.y))+tex2D(s0, float2(pos+c1, tex.y))+tex2D(s0, float2(pos+2*c1, tex.y))+tex2D(s0, float2(pos+3*c1, tex.y)))*.25;// blur and output
}



// vertical 4-pixel averaging, dithering, posterizing and old CRT scan lines
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 4

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.0625, .0625, .25);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z-.5), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.125)*c1.y*4.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y)))*.25;// blur input
#if posterizedegamma
s1 = pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*br;// modulate brightness and output
#else
s1 = round(s1*quantize+dithers);// dither and posterize
return s1*(br*quantizer);// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// vertical 4-pixel averaging, dithering, posterizing and old CRT scan lines for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 4

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.0625, .0625, .25);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z-.5), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.125)*c1.y*4.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y)))*.25;// blur input
#if posterizedegamma
s1 = pow(round(sqrt(s1*65535/32767.-16384/32767.)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*(br*32767/65535.)+16384/65535.;// modulate brightness and output
#else
s1 = round((s1*65535/32767.-16384/32767.)*quantize+dithers);// dither and posterize
return s1*(br*quantizer*32767/65535.)+16384/65535.;// shrink interval back to normal after posterization, modulate brightness and output
#endif
}


Maybe if you only try to draw the mask grille, not the other efects. (only a draw a mask in front the video)

Any way I found the source code for the shader mask, but am to :( about codes.

https://github.com/libretro/common-shaders/blob/master/crt/crt-geom-flat.cg

Also found this variants of the shader
http://emulation-general.wikia.com/wiki/CRT_Geom

and the image should look like this

http://images3.wikia.nocookie.net/__cb20130723004104/emulation-general/images/thumb/4/4c/Retroarch_2013-07-22_17-21-17-60.png/1000px-Retroarch_2013-07-22_17-21-17-60.png

JanWillem32
29th July 2013, 00:27
The host renderer for the shaders your link points to is organized very differently than the ones used for the shaders over here.
The first shaders I posted actually only blur and apply the scan line effect. The results are not stellar. The second version also properly degrades to low resolution and low quantization. It won't come close to pixel art like in that picture, but it will do a reasonable job on most typical video sources.
The default quantization in the shader is rather high compared to that picture. If it's a 256-color mode, try quantizationbits at 8/3., posterizedegamma 0 and probably a different gamma for the scan lines effect for the renderer in 8-bit mode or 17/6. and posterizedegamma 1 in quality mode. (Quality mode wastes a few percent at the top of the usual [0, 1] interval for two of the three channels.)
Note that I edited my previous post to fix a few bugs in the code with dithering and negative inputs.

turbojet
29th July 2013, 07:20
XRyche: can you post a short clip?

JanWillem32
29th July 2013, 08:36
Here are some extra shaders for larger pixels. I also edited the previous post because the forum has a maximum text length limit.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// horizontal 8-pixel averaging
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 8

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float pos = (trunc(tex.x*c0*.125)+.0625)*c1*8.;// calculate the left positon of the current set of pixels
return (tex2D(s0, float2(pos, tex.y))+tex2D(s0, float2(pos+c1, tex.y))+tex2D(s0, float2(pos+2*c1, tex.y))+tex2D(s0, float2(pos+3*c1, tex.y))+tex2D(s0, float2(pos+4*c1, tex.y))+tex2D(s0, float2(pos+5*c1, tex.y))+tex2D(s0, float2(pos+6*c1, tex.y))+tex2D(s0, float2(pos+7*c1, tex.y)))*.125;// blur and output
}



// vertical 8-pixel averaging, dithering, posterizing and old CRT scan lines
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 8

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.015625, .015625, .125);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.0625)*c1.y*8.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y)))*.125;// blur input
#if posterizedegamma
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*br;// modulate brightness and output
#else
s1 = round(s1*quantize+dithers);// dither and posterize
return s1*(br*quantizer);// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// vertical 8-pixel averaging, dithering, posterizing and old CRT scan lines for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 8

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.015625, .015625, .125);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.0625)*c1.y*8.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y)))*.125;// blur input
#if posterizedegamma
s1 = s1*65535/32767.-16384/32767.;
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*(br*32767/65535.)+16384/65535.;// modulate brightness and output
#else
s1 = round((s1*65535/32767.-16384/32767.)*quantize+dithers);// dither and posterize
return s1*(br*quantizer*32767/65535.)+16384/65535.;// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// horizontal 10-pixel averaging
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 10

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float pos = (trunc(tex.x*c0*.1)+.05)*c1*10.;// calculate the left positon of the current set of pixels
return (tex2D(s0, float2(pos, tex.y))+tex2D(s0, float2(pos+c1, tex.y))+tex2D(s0, float2(pos+2*c1, tex.y))+tex2D(s0, float2(pos+3*c1, tex.y))+tex2D(s0, float2(pos+4*c1, tex.y))+tex2D(s0, float2(pos+5*c1, tex.y))+tex2D(s0, float2(pos+6*c1, tex.y))+tex2D(s0, float2(pos+7*c1, tex.y))+tex2D(s0, float2(pos+8*c1, tex.y))+tex2D(s0, float2(pos+9*c1, tex.y)))*.1;// blur and output
}



// vertical 10-pixel averaging, dithering, posterizing and old CRT scan lines
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 10

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.0125, .0125, .1);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.05)*c1.y*10.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y))+tex2D(s0, float2(tex.x, pos+8*c1.y))+tex2D(s0, float2(tex.x, pos+9*c1.y)))*.1;// blur input
#if posterizedegamma
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*br;// modulate brightness and output
#else
s1 = round(s1*quantize+dithers);// dither and posterize
return s1*(br*quantizer);// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// vertical 10-pixel averaging, dithering, posterizing and old CRT scan lines for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 10

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.0125, .0125, .1);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.05)*c1.y*10.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y))+tex2D(s0, float2(tex.x, pos+8*c1.y))+tex2D(s0, float2(tex.x, pos+9*c1.y)))*.1;// blur input
#if posterizedegamma
s1 = s1*65535/32767.-16384/32767.;
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*(br*32767/65535.)+16384/65535.;// modulate brightness and output
#else
s1 = round((s1*65535/32767.-16384/32767.)*quantize+dithers);// dither and posterize
return s1*(br*quantizer*32767/65535.)+16384/65535.;// shrink interval back to normal after posterization, modulate brightness and output
#endif
}

fagoatse
29th July 2013, 09:34
The shaders jerrymh posted are meant to be used with emulators(RetroArch/Libretro in this case) and they are tailored for a specific resolution as far as I know. RetroArch supports up to 8 passes and you can build https://github.com/libretro/libretro-ffmpeg if you wish to test them in video playback scenario.

jerrymh
4th August 2013, 07:11
Here are some extra shaders for larger pixels. I also edited the previous post because the forum has a maximum text length limit.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// horizontal 8-pixel averaging
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 8

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float pos = (trunc(tex.x*c0*.125)+.0625)*c1*8.;// calculate the left positon of the current set of pixels
return (tex2D(s0, float2(pos, tex.y))+tex2D(s0, float2(pos+c1, tex.y))+tex2D(s0, float2(pos+2*c1, tex.y))+tex2D(s0, float2(pos+3*c1, tex.y))+tex2D(s0, float2(pos+4*c1, tex.y))+tex2D(s0, float2(pos+5*c1, tex.y))+tex2D(s0, float2(pos+6*c1, tex.y))+tex2D(s0, float2(pos+7*c1, tex.y)))*.125;// blur and output
}



// vertical 8-pixel averaging, dithering, posterizing and old CRT scan lines
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 8

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.015625, .015625, .125);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.0625)*c1.y*8.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y)))*.125;// blur input
#if posterizedegamma
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*br;// modulate brightness and output
#else
s1 = round(s1*quantize+dithers);// dither and posterize
return s1*(br*quantizer);// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// vertical 8-pixel averaging, dithering, posterizing and old CRT scan lines for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 8

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.015625, .015625, .125);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.0625)*c1.y*8.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y)))*.125;// blur input
#if posterizedegamma
s1 = s1*65535/32767.-16384/32767.;
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*(br*32767/65535.)+16384/65535.;// modulate brightness and output
#else
s1 = round((s1*65535/32767.-16384/32767.)*quantize+dithers);// dither and posterize
return s1*(br*quantizer*32767/65535.)+16384/65535.;// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// horizontal 10-pixel averaging
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 10

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float pos = (trunc(tex.x*c0*.1)+.05)*c1*10.;// calculate the left positon of the current set of pixels
return (tex2D(s0, float2(pos, tex.y))+tex2D(s0, float2(pos+c1, tex.y))+tex2D(s0, float2(pos+2*c1, tex.y))+tex2D(s0, float2(pos+3*c1, tex.y))+tex2D(s0, float2(pos+4*c1, tex.y))+tex2D(s0, float2(pos+5*c1, tex.y))+tex2D(s0, float2(pos+6*c1, tex.y))+tex2D(s0, float2(pos+7*c1, tex.y))+tex2D(s0, float2(pos+8*c1, tex.y))+tex2D(s0, float2(pos+9*c1, tex.y)))*.1;// blur and output
}



// vertical 10-pixel averaging, dithering, posterizing and old CRT scan lines
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 10

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.0125, .0125, .1);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.05)*c1.y*10.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y))+tex2D(s0, float2(tex.x, pos+8*c1.y))+tex2D(s0, float2(tex.x, pos+9*c1.y)))*.1;// blur input
#if posterizedegamma
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*br;// modulate brightness and output
#else
s1 = round(s1*quantize+dithers);// dither and posterize
return s1*(br*quantizer);// shrink interval back to normal after posterization, modulate brightness and output
#endif
}



// vertical 10-pixel averaging, dithering, posterizing and old CRT scan lines for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a vertical resolution that is evenly divisible by 10

#define gamma 1// higher is brighter, fractions, either decimal or not are allowed
#define scanlinebasedarken .5// the default of .5 will darken outer pixels a bit on each set of vertical pixels to appear like old CRT scan lines, higher values will narrow the scan line beam
#define posterizedegamma 1// 0 or 1, apply dirty de-gamma for posterization, useful to preserve realistic gradients in low gamma modes
#define quantizationbits 4// posterization level, note that 'quantize' can actually take any amount, not just those based on powers of two

sampler s0 : register(s0);
float2 c0 : register(c0);
float2 c1 : register(c1);
static const float quantize = pow(2, quantizationbits)-1;
static const float quantizer = 1./quantize;
static const float qm = .0078125*quantizer;
static const float smalldithermap[8][8] = {
{-63*qm, qm, -47*qm, 17*qm, -59*qm, 5*qm, -43*qm, 21*qm},
{33*qm, -31*qm, 49*qm, -15*qm, 37*qm, -27*qm, 53*qm, -11*qm},
{-39*qm, 25*qm, -55*qm, 9*qm, -35*qm, 29*qm, -51*qm, 13*qm},
{57*qm, -7*qm, 41*qm, -23*qm, 61*qm, -3*qm, 45*qm, -19*qm},
{-57*qm, 7*qm, -41*qm, 23*qm, -61*qm, 3*qm, -45*qm, 19*qm},
{39*qm, -25*qm, 55*qm, -9*qm, 35*qm, -29*qm, 51*qm, -13*qm},
{-33*qm, 31*qm, -49*qm, 15*qm, -37*qm, 27*qm, -53*qm, 11*qm},
{63*qm, -qm, 47*qm, -17*qm, 59*qm, -5*qm, 43*qm, -21*qm}};

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 basepos = tex.xyy*c0.xyy*float3(.0125, .0125, .1);
float3 basefrac = frac(basepos);
float2 lookups = basefrac.xy*8.;
float dithers = smalldithermap[lookups.x][lookups.y];

float br = 1.-pow(abs(basefrac.z*2.*scanlinebasedarken-scanlinebasedarken), gamma);// generate scan lines

float pos = (basepos.z-basefrac.z+.05)*c1.y*10.;// calculate the top positon of the current set of pixels
float4 s1 = (tex2D(s0, float2(tex.x, pos))+tex2D(s0, float2(tex.x, pos+c1.y))+tex2D(s0, float2(tex.x, pos+2*c1.y))+tex2D(s0, float2(tex.x, pos+3*c1.y))+tex2D(s0, float2(tex.x, pos+4*c1.y))+tex2D(s0, float2(tex.x, pos+5*c1.y))+tex2D(s0, float2(tex.x, pos+6*c1.y))+tex2D(s0, float2(tex.x, pos+7*c1.y))+tex2D(s0, float2(tex.x, pos+8*c1.y))+tex2D(s0, float2(tex.x, pos+9*c1.y)))*.1;// blur input
#if posterizedegamma
s1 = s1*65535/32767.-16384/32767.;
float4 signbits = sign(s1);
s1 = signbits*pow(round(sqrt(s1)*quantize+dithers)*quantizer, 2);// dither and posterize
return s1*(br*32767/65535.)+16384/65535.;// modulate brightness and output
#else
s1 = round((s1*65535/32767.-16384/32767.)*quantize+dithers);// dither and posterize
return s1*(br*quantizer*32767/65535.)+16384/65535.;// shrink interval back to normal after posterization, modulate brightness and output
#endif
}

Thanks, long time without internet. :mad:

jerrymh
4th August 2013, 17:49
I found this on libreto ffmpeg video shader, really looks like and old crt monitor , but dont know if there any build for windows

https://photos-2.dropbox.com/t/0/AAB0TgdA87Z8o0z--fUDPR3sdcXuJyIHpmvfdSaYd3L2Lg/12/149537/png/32x32/3/1375639200/0/2/RetroArch-0719-182234.png/0vm6SKy7KZQJmOAzkTFZ8f7lNzBL7vzYcDfVtaXnYqU%2C_iLphXBTqHEvh5k1JTJPn3pjPVrjYF6islARCB6XHlI?size=1280x960

JanWillem32
11th August 2013, 22:30
XRyche, I made a three-stage chain that might work. It's currently rather restricted and I'll probably need to change a few more parameters, but it's a good start. I only made one chain, meant for the combination of HD video with the renderer settings on 16-bit integer surfaces with the disable initial pass shaders option enabled. I can add more shaders later, if these work well.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// R'G'B' to Y'CbCr for HD video input for XYZ rendering on 16-bit integer surfaces

sampler s0;

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 s1 = tex2Dlod(s0, float4(tex, 0, 0)).rgb;// original pixel
return ((s1.rrr*float3(.2126, -.1063/.9278, .5)+s1.ggg*float3(.7152, -.3576/.9278, -.3576/.7874)+s1.bbb*float3(.0722, .5, -.0361/.7874))*32767/65535.+float3(16384/65535., 32767/65535., 32767/65535.)).rgbb;// HD RGB to Y'CbCr output
}



// horizontal pass sharpen complex, deband and denoise for HD video input for XYZ rendering on 16-bit integer surfaces

#define SharpenLimitLuma 2// valid interval [0, 10], luma-specific sharpening limit, 0 is disabled, lower numbers will allow more sharpening on contours
#define SharpenLimitChroma 2// valid interval [0, 10], chroma-specific sharpening limit, 0 is disabled, lower numbers will allow more sharpening on contours
#define LumaDetectionFactor 64// valid interval (65535/32767., 250], luma-specific detection factor, if set to the lowest amount no contours can be detected, higher numbers will shift the detection on color difference intervals of debanding to noise detection limit to mimimum sharpening to maximum sharpening toward more sharpening
#define ChromaDetectionFactor 64// valid interval (65535/32767., 250], chroma-specific detection factor, if set to the lowest amount no contours can be detected, higher numbers will shift the detection on color difference intervals of debanding to noise detection limit to mimimum sharpening to maximum sharpening toward more sharpening
#define NoiseThreshold .0078125// valid interval [0, 32767/65535.), banding treshold, higher numbers mean stronger deband and denoise

sampler s0 : register(s0);
float2 c1 : register(c1);
#define sp(a) tex2Dlod(s0, float4(tex+c1*float2(a, 0), 0, 0)).rgb
static const float3 slimits = float3(-SharpenLimitLuma, -SharpenLimitChroma, -SharpenLimitChroma);
static const float3 dfactors = float3(LumaDetectionFactor, ChromaDetectionFactor, ChromaDetectionFactor);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 n, p, s1 = sp(0);// original pixel
{
float3 s2 = sp(-1);
float3 af = 1.;// accumulated amount of colors from the samples
float3 ac = s1;// accumulate color
float3 cd = abs(s1-s2);// color difference
float3 rcd = max(slimits, 1.-dfactors*cd);// factor for both base and multiplicand is 1.0, the output will be in the interval (-inf, 1]
// invert interval on sharpening
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s2*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {// continue if all channels are below the noise threshold
float3 s3 = sp(-2);
cd = abs(s1-s3);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s3*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s4 = sp(-3);
cd = abs(s1-s4);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s4*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s5 = sp(-4);
cd = abs(s1-s5);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s5*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s6 = sp(-5);
cd = abs(s1-s6);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s6*rcd;
}
}
}
}
n = ac/af;
}
{
float3 s2 = sp(1);
float3 af = 1.;// accumulated amount of colors from the samples
float3 ac = s1;// accumulate color
float3 cd = abs(s1-s2);// color difference
float3 rcd = max(slimits, 1.-dfactors*cd);// factor for both base and multiplicand is 1.0, the output will be in the interval (-inf, 1]
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s2*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {// continue if all channels are below the noise threshold
float3 s3 = sp(2);
cd = abs(s1-s3);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s3*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s4 = sp(3);
cd = abs(s1-s4);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s4*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s5 = sp(4);
cd = abs(s1-s5);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s5*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s6 = sp(5);
cd = abs(s1-s6);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s6*rcd;
}
}
}
}
p = ac/af;
}
return ((n+p)*.5).rgbb;
}



// vertical pass sharpen complex, deband, denoise and color controls for HD video input for XYZ rendering on 16-bit integer surfaces

#define SharpenLimitLuma 2// valid interval [0, 10], luma-specific sharpening limit, 0 is disabled, lower numbers will allow more sharpening on contours
#define SharpenLimitChroma 2// valid interval [0, 10], chroma-specific sharpening limit, 0 is disabled, lower numbers will allow more sharpening on contours
#define LumaDetectionFactor 64// valid interval (65535/32767., 250], luma-specific detection factor, if set to the lowest amount no contours can be detected, higher numbers will shift the detection on color difference intervals of debanding to noise detection limit to mimimum sharpening to maximum sharpening toward more sharpening
#define ChromaDetectionFactor 64// valid interval (65535/32767., 250], chroma-specific detection factor, if set to the lowest amount no contours can be detected, higher numbers will shift the detection on color difference intervals of debanding to noise detection limit to mimimum sharpening to maximum sharpening toward more sharpening
#define NoiseThreshold .0078125// valid interval [0, 32767/65535.), banding treshold, higher numbers mean stronger deband and denoise

// YCbCrColorControls, 0 is disabled, 1 is enabled
#define YCbCrColorControls 0
// Brightness, interval [-10, 10], default 0
#define Brightness 0
// Contrast, interval [0, 10], default 1
#define Contrast 1
// GrayscaleGamma and ColorfulnessGamma, interval (0, 10], default 1
#define GrayscaleGamma 1
#define ColorfulnessGamma 1
// Hue, interval [-180, 180], default 0
#define Hue 0
// Saturation, interval [0, 10], default 1
#define Saturation 1
// VideoRedGamma, VideoGreenGamma and VideoBlueGamma, interval (0, 10], default 2.4, the video gamma input factors used to convert between the video input RGB and linear RGB
#define VideoRedGamma 2.4
#define VideoGreenGamma 2.4
#define VideoBlueGamma 2.4

sampler s0 : register(s0);
float2 c1 : register(c1);
#define sp(a) tex2Dlod(s0, float4(tex+c1*float2(0, a), 0, 0)).rgb
static const float3 slimits = float3(-SharpenLimitLuma, -SharpenLimitChroma, -SharpenLimitChroma);
static const float3 dfactors = float3(LumaDetectionFactor, ChromaDetectionFactor, ChromaDetectionFactor);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float3 n, p, s1 = sp(0);// original pixel
{
float3 s2 = sp(-1);
float3 af = 1.;// accumulated amount of colors from the samples
float3 ac = s1;// accumulate color
float3 cd = abs(s1-s2);// color difference
float3 rcd = max(slimits, 1.-dfactors*cd);// factor for both base and multiplicand is 1.0, the output will be in the interval (-inf, 1]
// invert interval on sharpening
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s2*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {// continue if all channels are below the noise threshold
float3 s3 = sp(-2);
cd = abs(s1-s3);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s3*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s4 = sp(-3);
cd = abs(s1-s4);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s4*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s5 = sp(-4);
cd = abs(s1-s5);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s5*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s6 = sp(-5);
cd = abs(s1-s6);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s6*rcd;
}
}
}
}
n = ac/af;
}
{
float3 s2 = sp(1);
float3 af = 1.;// accumulated amount of colors from the samples
float3 ac = s1;// accumulate color
float3 cd = abs(s1-s2);// color difference
float3 rcd = max(slimits, 1.-dfactors*cd);// factor for both base and multiplicand is 1.0, the output will be in the interval (-inf, 1]
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s2*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {// continue if all channels are below the noise threshold
float3 s3 = sp(2);
cd = abs(s1-s3);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s3*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s4 = sp(3);
cd = abs(s1-s4);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s4*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s5 = sp(4);
cd = abs(s1-s5);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s5*rcd;
[branch] if(max(max(cd.x, cd.y), cd.z) < NoiseThreshold) {
float3 s6 = sp(5);
cd = abs(s1-s6);
rcd = max(slimits, 1.-dfactors*cd);
if(rcd.x < 0) rcd.x = SharpenLimitLuma-abs(rcd.x);
if(rcd.y < 0) rcd.y = SharpenLimitChroma-abs(rcd.y);
if(rcd.z < 0) rcd.z = SharpenLimitChroma-abs(rcd.z);
af += abs(rcd);
ac += s6*rcd;
}
}
}
}
p = ac/af;
}
float3 t0 = (n+p)*.5;
t0 = t0*65535/32767.-float3(16384/32767., 32767/65535.+.5, 32767/65535.+.5);
#if YCbCrColorControls == 1
t0.yz = mul(t0.yz, float2x2(cos(radians(Hue)), sin(radians(Hue)), -sin(radians(Hue)), cos(radians(Hue))));// process hue
t0.xyz *= float3(Contrast, 2*Saturation, 2*Saturation);// process contrast and saturation, extend the chroma interval from [-.5, .5] to [-1, 1] for gamma processing
t0.x += Brightness;// process brightness
// preserve the sign bits of Y'CbCr values
float3 sby = sign(t0);
t0 = sby*pow(abs(t0), float3(GrayscaleGamma, ColorfulnessGamma, ColorfulnessGamma));// gamma processing
t0 = t0.rrr+float3(0, -.5*.1674679/.894, .5*1.8556)*t0.ggg+float3(.5*1.5748, -.5*.4185031/.894, 0)*t0.bbb;// HD Y'CbCr to RGB, compensate for the chroma ranges
#else
t0 = t0.rrr+float3(0, -.1674679/.894, 1.8556)*t0.ggg+float3(1.5748, -.4185031/.894, 0)*t0.bbb;// HD Y'CbCr to RGB
#endif
// preserve the sign bits of RGB values
float3 sbl = sign(t0);
t0 = sbl*pow(abs(t0), float3(VideoRedGamma, VideoGreenGamma, VideoBlueGamma));// linear RGB gamma correction
t0 = mul(t0, float3x3(0.3786675215, 0.1952504408, 0.0177500401, 0.3283428626, 0.6566857251, 0.1094476209, 0.1657219631, 0.0662887852, 0.8728023391))*32767/65535.+16384/65535.;
return t0.rgbb;// XYZ output
}

JanWillem32
11th August 2013, 22:33
The "contour color expose banding" shader is useful for denoise and deband testing purposes.// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// contour color expose banding for XYZ rendering on 16-bit integer surfaces
// This shader can be run as a screen space pixel shader.
// This shader requires compiling with ps_2_0, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// Use this shader to add a color contoured effect to an image.

sampler s0;
float2 c1 : register(c1);
#define sp(a, b, c) float4 a = tex2D(s0, tex+c1*float2(b, c));

float4 main(float2 tex : TEXCOORD0) : COLOR
{
sp(s2, -1, -1) sp(s3, 0, -1) sp(s4, 1, -1) sp(s5, -1, 0) sp(s6, 1, 0) sp(s7, -1, 1) sp(s8, 0, 1) sp(s9, 1, 1)// sample surrounding pixels
return smoothstep(.0625, 0, abs(s2+s3+s4-s7-s8-s9)+abs(s2+s5+s7-s4-s6-s9)+abs(s2+s3+s5-s6-s8-s9)+abs(s3+s4+s6-s5-s7-s8))*32767/65535.+16384/65535.;// color contour output
}

JanWillem32
12th August 2013, 08:23
I just wrote some simple shaders for usage as a third pass, after the "vertical x-pixel averaging, dithering, posterizing and old CRT scan lines"-type shaders. These shaders separate RGB channels of the input video into multiple real pixels, imitating aperture grilles that use rectangular masks. (Imitating the other common shadow mask pattern would be a lot harder to program. I'm not sure it's worth the effort.) The warnings about divisibility in these shaders are not that important. The artifacts are barely visible if the input isn't evenly divisible.// horizontal 4-pixel RGB separation
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 4

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.25;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .25) mask = float4(1, 0, 0, 0);
else if(posdif < .5) mask = float4(0, 1/3., 2/3., 0);
else if(posdif < .75) mask = float4(0, 2/3., 1/3., 0);
else mask = float4(0, 0, 1, 0);
return tex2D(s0, tex)*mask;// mask and output
}



// horizontal 5-pixel RGB separation
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 5

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.2;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .2) mask = float4(1, 0, 0, 0);
else if(posdif < .4) mask = float4(0, 2/3., 1/3., 0);
else if(posdif < .6) mask = float4(0, 1, 0, 0);
else if(posdif < .8) mask = float4(0, 1/3., 2/3., 0);
else mask = float4(0, 0, 1, 0);
return tex2D(s0, tex)*mask;// mask and output
}



// horizontal 8-pixel RGB separation
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 8

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.125;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .25) mask = float4(1, 0, 0, 0);
else if(posdif < 0.375) mask = float4(0, 2/3., 1/3., 0);
else if(posdif < 0.625) mask = float4(0, 1, 0, 0);
else if(posdif < .75) mask = float4(0, 1/3., 2/3., 0);
else mask = float4(0, 0, 1, 0);
return tex2D(s0, tex)*mask;// mask and output
}



// horizontal 10-pixel RGB separation
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 10

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.1;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .3) mask = float4(1, 0, 0, 0);
else if(posdif < .4) mask = float4(0, 1/3., 2/3., 0);
else if(posdif < .6) mask = float4(0, 1, 0, 0);
else if(posdif < .7) mask = float4(0, 2/3., 1/3., 0);
else mask = float4(0, 0, 1, 0);
return tex2D(s0, tex)*mask;// mask and output
}



// horizontal 4-pixel RGB separation for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 4

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.25;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .25) mask = float4(1, 0, 0, 0);
else if(posdif < .5) mask = float4(0, 1/3., 2/3., 0);
else if(posdif < .75) mask = float4(0, 2/3., 1/3., 0);
else mask = float4(0, 0, 1, 0);
return (tex2D(s0, tex)-16384/65535.)*mask+16384/65535.;// mask and output
}



// horizontal 5-pixel RGB separation for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 5

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.2;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .2) mask = float4(1, 0, 0, 0);
else if(posdif < .4) mask = float4(0, 2/3., 1/3., 0);
else if(posdif < .6) mask = float4(0, 1, 0, 0);
else if(posdif < .8) mask = float4(0, 1/3., 2/3., 0);
else mask = float4(0, 0, 1, 0);
return (tex2D(s0, tex)-16384/65535.)*mask+16384/65535.;// mask and output
}



// horizontal 8-pixel RGB separation for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 8

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.125;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .25) mask = float4(1, 0, 0, 0);
else if(posdif < 0.375) mask = float4(0, 2/3., 1/3., 0);
else if(posdif < 0.625) mask = float4(0, 1, 0, 0);
else if(posdif < .75) mask = float4(0, 1/3., 2/3., 0);
else mask = float4(0, 0, 1, 0);
return (tex2D(s0, tex)-16384/65535.)*mask+16384/65535.;// mask and output
}



// horizontal 10-pixel RGB separation for XYZ rendering on 16-bit integer surfaces
// this shader only works properly on inputs that have a horizontal resolution that is evenly divisible by 10

sampler s0 : register(s0);
float c0 : register(c0);
float c1 : register(c1);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float scaletexx = tex.x*c0*.1;
float prepos = trunc(scaletexx);// calculate the left positon of the current set of pixels
float posdif = scaletexx-prepos;
float4 mask;// create RGB mask based on the pixel location
if(posdif < .3) mask = float4(1, 0, 0, 0);
else if(posdif < .4) mask = float4(0, 1/3., 2/3., 0);
else if(posdif < .6) mask = float4(0, 1, 0, 0);
else if(posdif < .7) mask = float4(0, 2/3., 1/3., 0);
else mask = float4(0, 0, 1, 0);
return (tex2D(s0, tex)-16384/65535.)*mask+16384/65535.;// mask and output
}

leeperry
11th November 2013, 23:54
Hi Jan,

So following your advice in another thread that was asking for a "film grain" PS script, I've played around with your "semi-random grayscale noise.txt" which looks quite good but do you think it would be possible to make a PS script version of GrainFactory3() (http://forum.doom9.org/showpost.php?p=1191292&postcount=30)?

It allows you to choose the size, strength and sharpness of grain depending on dark/mid-tone/bright areas(whose limits can also be defined) and it can really be finetuned either for deblocking purposes, grain-based EE or artistic effects meant to mimick reel grain.

The problem with Didée's script is that it quickly becomes a CPU hog, Avisynth works in 8bit only and the idea would be to process it in 32fp after scaling to Jinc3AR in mVR....so if there is any way you could work your magic to do the same within a PS script, this would be too good to be true :)

:thanks: you very much in advance for even considering it,

JanWillem32
12th November 2013, 05:37
What I could find out about GrainFactory3 was: "noise generator that tries to simulate the behaviour of silver grain on film".
I already wrote some basic noise effect shaders, but maybe I could get closer to the look of silver grain on film.
When I start coding to create an effect, I start with looking at examples on images. I don't just duplicate/imitate other filters. When I've gathered enough research materials, I just start writing out possible parameters for methods in an effect. After that, I try a few methods. These are just calculations that spring to mind, and I usually copy a lot of previously written methods, too. After a bit of tinkering, I usually get the desirable effect from a shader. When transforming the prototype shader to a final type, I optimize first, and add comments. After that, I extract the set of constants, give them names and offer them as user-configurable parameters.
The reason I'm telling this is simple; I can practically guarantee that once I've finished something that resembles silver grain on film, the effect will not have a grand total 19 user input variables like GrainFactory3.
On the other hand, I don't see any options in GrainFactory3 for using color. I would probably add an option or options for this type of filter related to color, for example; to use the properties for sepia toning instead of silver. (This possibly requires separate filters, though.)

To start off simple, the pictures I could find of real film used in cinemas varied strongly over the decades. The most evident changes were the transition from grayscale or toned video to color. The form and amount of grain on film, and the cinema equipment varied, too. Some effects are available: projector film drive scratches, projector film dust, projector film lamp vignette, projector film sepia toning for SD&HD video input, grayscale, projector film shaking, semi-random colored surface noise and semi-random grayscale noise.
What era are you targeting for this kind of vintage look? Which effects are currently missing to complete the illusion of such a look? Please specify with some true vintage cinematic examples and name some very specific factors.

leeperry
12th November 2013, 18:17
Hi Jan, thanks for the swift reply.

Well, it would appear that to simulate silver film grain you'd need the ability to set different chunk sizes for dark/mid/bright pixels as grain would appear to look thicker in dark areas for instance. I think 21 grams (http://www.google.com/search?q=21+grams&tbm=isch) is a good example of what excessive reel grain can do, of course I want to keep it less intrusive.

My real-world use of GrainF3 was to set very low values in order to deblock(which tends to increase the subjective pop-effect IME), add some subtle grain-based EE, give a DLP/silver reel look to sanitized "flat looking" digital movies the same way DLP videoprojectors look pretty grain in dark areas due to their very fast rotating mirrors (http://www2.hesston.edu/Physics/TelevisionDisplays/IMAGES/DLP.JPG) for instance.

I don't think I would be interested in chroma grain, but I would need is the abilities to:
-choose the size and strength of grain depending on dark/mid/bright areas
-choose the limits for dark/mid/bright, like in GrainF3
-choose the grain pattern or make it random, much like what foxyshadis explained here (http://forum.doom9.org/showpost.php?p=1403328&postcount=40). Once you find your favorite grain patterns for dark/mid/bright areas, you can use them permanently and the "movie grain" won't be quite random anymore as it'll be finetuned to your liking.

The intent of GrainF3 is not to mimick a 1930's sepia looking semi-busted projector but simply to add (possibly very subtle) silver looking grain. Once finetuned, it can really look great as adding grain does wonders for deblocking purposes IME. Of course it can also be used with excessive settings for artistic means.

The more I talk about it, the more I wanna play around with GrainF3 all over again but I would really rather have it done via a PS script for all the aforementioned reasons :)

PS: ouh, this looks impressive too: Cinema Film Grain Plugin for FCPX (http://www.fcpeffects.com/products/cinema-film-grain) :cool:

leeperry
9th December 2013, 18:17
Hi again Jan, so I've tried my old GrainF3() calls that looked so great on CRT/DLP but they look darn noisy on LCD....would have to rework them again from scratch with much more subtle settings I guess.

Anyway, I've got a question for you :)

Here's another Avisynth script that has always impressed me: SmoothLevels() (http://forum.doom9.org/showthread.php?t=154971)

It's gone DLL but it used to be an .AVS script and here are a few older versions of it: SmoothLevels.rar (11 KB) (https://mega.co.nz/#!K0AlXLCK!VDlGv12GxSIiqSLgStdGQHXl2sEacjiVcvQanTI0oG8)

Using it to convert TV to PC, I've always found its resulting picture to look "deeper" and simply more 3D-looking than whatever ffdshow or madVR could offer.

I mentioned it to madshi a while ago who told me that its error diffusion was technically more advanced than the dithering currently done in mVR and that PS scripts couldn't process Floyd-Steinberg.

I've made screenshots comparisons on a gray ramp and a REC709 test pattern available at SmoothL2.rar (15.3 MB) (https://mega.co.nz/#!f9wCUa5a!KdRNjFkmCuL9p_xz2yPcnWuN8uZ6iBVjwLZfvvhhc68)

I'm colorblind so judging on banding and colorimetry is a very tedious task for me, but I've been told that banding didn't look any better than in mVR and that it seemed to make colorimetry shifts?

Comparing screenshots back and forth it would appear to me that SmoothL is doing some sort of colorimetry-based EE? The borders of the color squares in that REC709 pattern look quite different with SmoothL, don't they?

My point is that for instance in this very short sample Prisoners.mkv (22.9 MB) (https://mega.co.nz/#!HtwVTBYa!ZYBMzxAkSPBBxcmyr06Hp1heUW8uqMuFPcgzfYFWUuQ) when comparing SmoothLevels(preset="tv2pc",HQ=true) to anything else, that animal in the woods seems to appear much deeper in the picture and the passing cars on the road feel less "flat" and far more natural to me :cool:

"HQ" would stand for "HQ interpolation" BTW.

All this said, do you agree that the picture looks deeper with that sample when using SmoothL? Is that because its error diffusion is more advanced than what mVR can do, or because of some -as I'm suspecting- colorimetry-based EE? If so, could you possibly provide the same kind of trick with a PS script?

My problem is that SmoothL outputs 8bit from ffdshow to mVR, it's a real CPU hog(especially in HQ mode on 1.78 1080p) and I'm totally hooked to its 3D look :o

Hope you can look into it, :thanks: in advance!

foxyshadis
13th December 2013, 18:05
Hi Jan! Excellent work with the new filters. Can I request that the main archive be updated to include the last couple of years' work, as well? I know some aren't 100% finished, but it'd be nice to have them all handy for quick downloading onto the various systems I have set up for media.

vBm
13th December 2013, 21:32
Would be quite nice to have centralized repository for all the shaders.

JanWillem32
17th December 2013, 15:41
leeperry, sorry that I took a while to give a status update. I've tried several prototype shaders for the grain/noise effects. None are really finished yet, and it's going to take some more development. I'm currently struggeling with getting larger, well-shaped, random grain particles efficiently in the output images. The prototype shaders are currently hardly any better than the simple types I already made before. (projector film dust, projector film drive scratches, semi-random colored surface noise and semi-random grayscale noise) The shaders that do generate larger grain particles generate nasty artifacts, and the shaders that generate the medium to fine noise are very per-pixel randomized.

As for "chroma grain", I'm not going to use any Y'CbCr channels for this shader, neither luma nor chroma. I do occasionally use the chroma parameter of CIECAM02 for some color-related filtering, but in this case that's not relevant at all. For the grayscale, toned (such as sepia) and three-layered film types, the grain/noise modifies the intensity of each tinted chemical applied on the film. At the moment I unfortunately still have to guess which xyY primary color (or color function) each of these tinted chemicals govern for both the recording as the playback phases, but I'll research that some more. If anybody knows these details, please notify me.

I'm not going to add support for textured patterns. It's extremely impractical from the renderer's perspective with the current interfaces, hardware support and file management. Of course the renderer does have easy access to internal resources. I'll elaborate more on that point later.

Multiple general shapes and sizes for the grain in the shaders shoud be possible, but it's currently not that easy to configure with the prototypes.

For shaders that do color corrections, I already wrote quite a few already. These all need to be edited though. The descriptions in these shaders are sub-par. I also wrote some new prototypes. I'll publish some implementations of these at a later date.

Dithering is a complicated transformation done in the absolute final filtering pass of a video renderer. I'm not going to write a dithering filter outside the context of exactly that.
Floyd–Steinberg dithering is due to its filtering kernel indeed unsuitable for pretty much any modern dithering method, including the dithering done in pixel shading passes. There are plenty of good alternatives in ordered dithering and such. I already wrote three modes to dither for a final filtering pass, and I'll happily add more modes if another suitable method pops up, but for now, I'm not going to write more dithering filters.

As for banding, when using either of the two advanced video renderers currently available for filtering; it's pretty much always a problem in the video source. For video filters that don't keep much quality in quantization and dynamics during filter transformations, additional banding will indeed occur. Debanding the source is quite a difficult problem. I've written several filters that can more or less deband a bit. (Don't expect much from the debanding filters with only a small filtering radius.)

As for the other effects you name that you attribute to SmoothLevels(), there's only so much you can transform in a width-height-color-time domain. A different ditherer isn't going to make things "appear much deeper" or "less flat". That's something generally achieved by sharpening, contrast enhancements or even gamma controls. I've written several of these filters already.

foxyshadis and vBm, as I mentioned in the main MPC-HC thread here on the software players board:The Pixel Shader Pack v1.5 will need quite a lot of extra work. I don't like the blocks of comments below the title of the shaders. It still mentions "screen space pixel shader" and such, which is just outdated. I also want to split the entire set of shaders per rendering color space+format. I'll have to add a 'readme' to properly document what to use in what renderer for that. Most of the pixel shaders are already available as multi-version (see the last few pages of the shader thread for examples).
Some shaders need to be scrapped for the simple reason that they should never be used (or I'll just put them in the junk folder called 'development'). I also wrote new shaders and corrected some wrong methods in older ones.
My main problem is actually the set of newly developed shaders. These hardly contain any comments, and some of them are just not user-friendly. I just don't have time to edit and test over 350 files.I just write a lot of, well... crap. There are a lot of prototype and 'finished' shaders that I should really edit to make them decent. Some other shaders need to be dumped in the 'development' junk folder with correct comments inside. And again some others can just be deleted. Just collecting all shaders in their current state isn't going to help at all.

leeperry
17th December 2013, 16:30
As for the other effects you name that you attribute to SmoothLevels(), there's only so much you can transform in a width-height-color-time domain. A different ditherer isn't going to make things "appear much deeper" or "less flat". That's something generally achieved by sharpening, contrast enhancements or even gamma controls. I've written several of these filters already.
Hi Jan, thanks for the reply!

I've played around with SmoothL quite a bit lately and I still suspect it to be processing chroma-based EE, isn't that possible whatsoever?

Could you please try the aforemetioned sample and SmoothL Avisynth call and see for yourself what it does? It looks like EE to me, but not the usual halo-based luma EE, there is no halo as far as I can tell and yet things look a bit like a cell-shade cartoon to me...there's more to it than what it would appear IMO. Or maybe it does mess with gamma on high contrast edges if that's even possible? I wish I could find proper test patterns to find out wth it does :sly:

All this said, it outputs 8bit to mVR so noise quickly becomes an issue and it's a CPU hog when OTOH mVR is able to process the TV>PC conversion with lower banding off a low GPU load at that.

Also, its subjective EE is impressive at first, much like Samsung's DNIE but they both kinda look "artificial" to me....if you could find out what the trick is, you could possibly allow us to finetune it using much weaker settings :)

FWIW, SmoothL supports a "debug=true" argument that shows all kinds of histograms in real time.

JanWillem32
18th December 2013, 19:50
leeperry, I just tested SmoothLevels().
I'm sorry but I can't really see much difference beyond the obviously clipped levels beyond the {[16, 235], [16, 240], [16, 240]} intervals in synthethic tests. I tested "SmoothLevels(preset="tv2pc",HQ=true)" with the "Prisoners.mkv" sample, with input intervals set to [0, 255] for the conversion to RGB. I compared it with the regular conversion without SmoothLevels() and the regular {[16, 235], [16, 240], [16, 240]} input intervals setting.
Note that for some reason the the "Prisoners.mkv" sample with a resolution of 1280×720 pixels was set to an anamorphic display ratio of 1279:720. I removed the anamorphic ratio before testing to prevent distortions.
Here's a link containing the two screenshots, taken of frame 600 of the sample, and the absolute diffence result: - .
The absolute difference in terms of R'G'B' is mostly 0.. The maximum difference is 6./255., in the form of some completely blue diffences on some of the sides of a tree.
The differences are mostly scattered R'G'B' pixels, but some groups can be seen on the sides of the trees and there are some patches on the brighter areas. The difference map also shows that only rarely combinations of R', G' and B' differences are found in the same pixel, pointing that there's not much change in brightness/luminance/contrast/luma/lightness.
My analysis is that all of this is mostly due to different dithering and dithering twice over, and not much else. Did I do something wrong during testing?

leeperry
19th December 2013, 02:52
Ah....So what did you compare "SmoothLevels(preset="tv2pc",HQ=true)" to exactly? mVR's TV to PC conversion?

Yes, the sides of the trees look different to me with SmoothL and the difference I'm seeing is definitely not placebo as I was able to DBT it with the help of a friend :o

I just recompared the REC709 test patterns from SmoothL2.rar (15.3 MB) (https://mega.co.nz/#!f9wCUa5a!KdRNjFkmCuL9p_xz2yPcnWuN8uZ6iBVjwLZfvvhhc68) and it seems clear that SmoothL outputs a higher level of dithering(I disabled dithering in mVR when using SmoothL), but maybe my brain likes it better because it's more advanced than what mVR is able to achieve...madshi made it clear that it's technically impossible to implement error diffusion with PS but that it might be possible with OpenCL/CUDA(which mVR does not support yet).

So you did write PS scripts for dithering? Would they be more efficient than what mVR currently does? No error diffusion I guess?

:thanks:

JanWillem32
19th December 2013, 07:04
I didn't use a video renderer. I compared the regular dithered output 8-bit R'G'B' by ffdshow tryouts' conversion. The internal {[16, 235], [16, 240], [16, 240]} intervals conversion to full range and that of SmoothLevels() doesn't differ all that much. The only consequence of letting SmoothLevels() is that the image is converted to YV12 in between expanding the levels and converting to R'G'B'. The consequence is dithering twice over, which is visible, but not really a good thing (I don't like adding noise at all).
The easiest 'dither' to implement is a random dither. You need to apply a lot of it so that it actually works, but it's not an elegant way of handling the issue. Example: http://caca.zoy.org/wiki/libcaca/study/1
Next are the static and random ordered dithering, which use a matrix. These require some attention on implementing, but these are very efficient single-level dithering methods. Example: http://caca.zoy.org/wiki/libcaca/study/2
Error diffusion and other methods are either pixel-progressive or multi-pass. This makes them very undesirable in modern systems. I'm not even going to attempt to implement one of those. Examples: http://caca.zoy.org/wiki/libcaca/study/3 and http://caca.zoy.org/wiki/libcaca/study/4
In general, if you want better dithering, just use a larger matrix for random ordered dithering. The other options would make due to performance problems no sense at all.
In terms of comparing my work to madVR, that's not easy. Because madVR has had a good many years of active development, it has many options. I however can't compare the internal code. I generally write really efficient, but wonderfully complicated code/assembly, that's for sure.

leeperry
19th December 2013, 19:18
Oh, I'm only parroting what madshi said: http://forum.doom9.org/showpost.php?p=1594415&postcount=14334
Screenshots are always converted to 8bit fullrange RGB (0-255), using error diffusion, which is a higher quality dithering algorithm compared to what madVR does during playback.
http://forum.doom9.org/showpost.php?p=1594420&postcount=14336
Error diffusion can't be done with GPU pixel shaders because error diffusion processes one pixel at a time, using the result of the previous pixel calculation for the next pixel. GPU pixel shaders more or less work on all pixels at the same time, which is the opposite of what error diffusion needs. *Maybe* it might be possible to do error diffusion using OpenCL/CUDA, but it will be difficult to do and likely not perform very well. For screenshots error diffusion is easy because madVR is doing the screenshot processing via CPU instead of GPU.
IIRC He told me that SmoothL does use error diffusion and that it wouldn't be possible in mVR without resorting to OpenCL/CUDA.

So you're saying that SmoothL does double dithering, interesting! I know many ppl used to enjoy my MT("GrainFactory_MT2 (http://pastebin.com/H6fDkSBp)(3,5,100,100,1.0,0.7,0,0,0,96,0)",4) call as much I did, so I guess my brain likes grain after all..I might just try some of your scripts for moar dither "grain" :)

romulous
29th December 2013, 04:51
Hi JanWillem32,

I was looking for a rotation PS (to rotate video files captured via mobile devices in portrait mode for example) - I just tried your "flip and rotate sampling direction for RGB" (for your v1.4 pack) in MPC-HC, and I finally managed to get it to load. Question - is this what the output is supposed to look like?
http://i.imgur.com/m3cNrQ3.jpg

If so, I have badly misunderstood what the PS is meant to do (I was looking for one that can rotate an entire video 90 degrees, 180 degrees, 270 degrees etc depending on how the person who filmed it was holding their camera at the time).

This is the same frame in the actual video itself for comparison with the PS:
http://i.imgur.com/pE0VuVR.jpg (as you can see, all this video requires is a simple 90 degree clockwise rotation)

Thanks.

JanWillem32
29th December 2013, 17:33
That shader performs an effect to flip and rotate each R, G and B channnel every frame on square textures.
You are probably looking for the renderer rotation effects. These are listed in the menus for resizing, rotation, pan and scan, et cetera, if available. Not all video renderers support this feature. (I wrote one with only partial support.) If that doesn't work, I can write a shader that does 90 degrees rotation, horizontal flipping and vertical flipping.
Note that geometry changes due to rotation usually require manual compensation, as the video renderer host usually doesn't compensate for it automatically.

romulous
30th December 2013, 02:48
You are probably looking for the renderer rotation effects.


Correct - I'm looking for a way to rotate entire videos. These will mainly be videos shot on mobile devices where the user has the camera not pointing the right way up. Here's an example posted here on Doom9 previously for this very thing:
http://www39.zippyshare.com/v/28485654/file.html


Not all video renderers support this feature. (I wrote one with only partial support.)


Heh - I wish I had asked here first before spending the entire day yesterday working on this (worked with your PS, various playing software, and a freely available DS rotation filter and that's the conclusion I came to).

The player I use is Zoom Player, and we have had an increasing number of people asking for video rotation, so I went looking for a solution. The only native Windows player so far that I have found that can do video rotation is MPC-BE, and only when using its own EVR CP (which doesn't help folks wanting the feature in other players such as Zoom).


If that doesn't work, I can write a shader that does 90 degrees rotation, horizontal flipping and vertical flipping.
Note that geometry changes due to rotation usually require manual compensation, as the video renderer host usually doesn't compensate for it automatically.

That would be great if it isn't too much trouble :) Zoom doesn't support PS as yet, but Blight is willing to add it as madVR already supports them (so only player support is required). I don't actually create mobile videos myself, but from what I've seen from samples various folk have posted, most seem to require a 90 degrees clockwise rotation, though I don't suppose you could really rule out a 90 degrees counter-clockwise rotation or maybe even a full 180 (how many different ways can you hold a camera that is not the correct way up?).

JanWillem32
31st December 2013, 02:47
The only native Windows player so far that I have found that can do video rotation is MPC-BE, and only when using its own EVR CP (which doesn't help folks wanting the feature in other players such as Zoom).In my honest opinion, rotation options should be implemented natively in the video renderer's mixer or resizer filtering passes. A separate pixel shader can do rotations, but these are not ideal. It's not efficient nor user-friendly. The efficient way of implementing these transforms is by using custom vertices for sampling the source texture (which in turn can be fed to any pixel shading pass in a single, combined transform). A separate pixel shader can't properly adjust the global resizing factor to fit an image nicely on screen (except when you only use the flip horizontal and flip vertical options which don't change geometry).
I'm well aware that there is no DirectShow interface to regulate video rotation, and integrated renderer filters such as this one are difficult to implement. I'll try to write a basic rotation shader today.I don't actually create mobile videos myself, but from what I've seen from samples various folk have posted, most seem to require a 90 degrees clockwise rotation, though I don't suppose you could really rule out a 90 degrees counter-clockwise rotation or maybe even a full 180 (how many different ways can you hold a camera that is not the correct way up?).180 degrees rotation is done by setting both 'flip horizontal' and 'flip vertical' options, 270 degrees rotation is done by setting all three options. I'll put that in the comments.

romulous
31st December 2013, 07:30
In my honest opinion, rotation options should be implemented natively in the video renderer's mixer or resizer filtering passes.

Indeed, Blight agrees - which is why he asked madshi to add it to madVR a while back. It's low on his to-do list though (and at the moment, madshi is not doing feature requests at all, so this will be a long time coming I'm afraid).


I'm well aware that there is no DirectShow interface to regulate video rotation, and integrated renderer filters such as this one are difficult to implement. I'll try to write a basic rotation shader today.

Thanks, at least that will be something in the meantime. For anyone wondering, this is the rotate filter I was testing:
http://videoprocessing.sourceforge.net/#rotate

Freeware and open source. It only works in RGB24 or RGB32, so you do have to load the colour space converter filter as well. 180 degree rotation works fine, as does vertical and horizontal (though vertical seems to not actually change the image in any way). 90 degrees, 270 degrees and diagonal all produce garbled images though:
http://i.imgur.com/4riVR5p.jpg

I'm told that would be because none of the video renderers support dynamic resolution changing, and that test clip is not the same width as it is height (meaning when you rotate it in certain ways, the resolution will change).

pirlouy
31st December 2013, 13:37
@JanWillem32: I'm quite sure you won't be interested, but maybe curiosity will persuade you.

Samsung TV offers a setting called "Dynamic Contrast" in options (not "CE dimming"), which changes original image, but I find it to be "nice looking" sometimes. You have 3 settings, but "low" is the best, 2 others change image too much.

Do you think you could write a shader for this, or it would me more complicated for the GPU ?
I suppose it changes pixel like this:
(post-resized by renderer)
Old Pixel: R=50; G=40; B=230
New Pixel:
R= 50+((50-128)*5%) = 46 (rounded)
G= 40+((40-128)*5%) = 36 (rounded)
B= 230+((230-128)*5%) = 235 (rounded)

Do you think my reasoning is stupid ?:confused:
Is there a simple way to test this algorithm with MPC ?

fagoatse
31st December 2013, 14:15
@JanWillem32: I'm quite sure you won't be interested, but maybe curiosity will persuade you.

Samsung TV offers a setting called "Dynamic Contrast" in options (not "CE dimming"), which changes original image, but I find it to be "nice looking" sometimes. You have 3 settings, but "low" is the best, 2 others change image too much.

Do you think you could write a shader for this, or it would me more complicated for the GPU ?
I suppose it changes pixel like this:
(post-resized by renderer)
Old Pixel: R=50; G=40; B=230
New Pixel:
R= 50+((50-128)*5%) = 46 (rounded)
G= 40+((40-128)*5%) = 36 (rounded)
B= 230+((230-128)*5%) = 235 (rounded)

Do you think my reasoning is stupid ?:confused:
Is there a simple way to test this algorithm with MPC ?

AFAIK the dynamic contrast option works by measuring ambient light in one's room so I guess it's impossible to simulate it correctly using shaders alone.

JanWillem32
1st January 2014, 00:00
romulous, this shader will work for now. I can also write a variant that masks the artifacts that occur when using diagonal flipping on rectangular textures.

pirlouy, that's a static contrast method. It's away from gray, and will crush near-black and near-white in the process. I don't like static nor dynamic contrast filters, as these always cause distortion. (I've already written several static contrast methods already, nonetheless.)
It's possible to do correct enviroment light adaptations (see the CIECAM02 transforms for reference). These filters require a lot of parameters, but are reasonably simple otherwise. These filers don't offer 'low'/'medium'/'high' options by the way. There's no place for user preferences in such filters. The ambient light factors can both be measured and estimated (again, see the CIECAM02 shader).

Example shader code (a funny one, as it only requires sampling a pixel and one multiply-add operation):#define CenterValueRed .5
#define CenterValueGreen .5
#define CenterValueBlue .5
#define ContrastRed .05
#define ContrastGreen .05
#define ContrastBlue .05
static const float4 Contrast = 1.+float4(ContrastRed, ContrastGreen, ContrastBlue, 0.);
static const float4 ScaledCenterValue = float4(CenterValueRed*ContrastRed, CenterValueGreen*ContrastGreen, CenterValueBlue*ContrastBlue, 0.);

sampler s0 : register(s0);

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 s1 = tex2D(s0, tex);// original pixel
return s1*Contrast-ScaledCenterValue;// process contrast and output
}// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// flip and rotate
// This shader shoud be run as a screen space pixel shader when enabling diagonal flipping, else both modes will work.
// This shader requires compiling with ps_2_0, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// If possible, avoid compiling with the software emulation modes (ps_?_sw). Pixel shaders require a lot of processing power to run in real-time software mode.
// This shader can flip and rotate full images.
// Note than when enabling diagonal flipping, the resizing factor has to be lowered in advance to allow the full image to be visible.

// FlipHorizontal, FlipVertical and FlipDiagonal: 0 is disabled, 1 is enabled
// To rotate by a quarter clockwise, enable FlipHorizontal and FlipDiagonal.
// To rotate by a half, enable FlipHorizontal and FlipVertical.
// To rotate by a quarter counter-clockwise, enable FlipVertical and FlipDiagonal.
#define FlipHorizontal 0
#define FlipVertical 0
#define FlipDiagonal 0

sampler s0;
#if FlipDiagonal
float2 c0;
float2 c1;
#endif

float4 main(float2 tex : TEXCOORD0) : COLOR
{
tex -= .5;
#if FlipHorizontal && FlipVertical
tex = -tex;
#elif FlipHorizontal
tex.x = -tex.x;
#elif FlipVertical
tex.y = -tex.y;
#endif
#if FlipDiagonal
tex = tex.yx*c1*c0.yx;
#endif
return tex2D(s0, tex+.5);// sample and output
}

romulous
1st January 2014, 01:46
romulous, this shader will work for now. I can also write a variant that masks the artifacts that occur when using diagonal flipping on rectangular textures.

Hi Jan,

Thanks - just trying it out in MPC-HC now (using madVR). Just testing the 90 degrees clockwise flip to begin with. On some of the videos, I see this (I tested 5 videos, these occurred on 4 of them - the remaining video was fine):
http://i.imgur.com/AcbOWwi.png

Is that the artifacts that you were referring to, or are these different ones?

Thanks!

JanWillem32
1st January 2014, 04:06
This shader is a little bit heavier, but can mask artifacts:// (C) 2013 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// flip and rotate with background mask
// This shader shoud be run as a screen space pixel shader when enabling diagonal flipping, else both modes will work.
// This shader requires compiling with ps_2_0, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// If possible, avoid compiling with the software emulation modes (ps_?_sw). Pixel shaders require a lot of processing power to run in real-time software mode.
// This shader can flip and rotate full images.
// Note than when enabling diagonal flipping, the resizing factor has to be lowered in advance to allow the full image to be visible.

// FlipHorizontal, FlipVertical and FlipDiagonal: 0 is disabled, 1 is enabled
#define FlipHorizontal 0
#define FlipVertical 0
#define FlipDiagonal 0
// BackgroundMask: red, green, blue and alpha vector to return on border values when FlipDiagonal is activated, intervals [0, 1]
#define BackgroundMask float4(0., 0., 0., 0.)

sampler s0;
#if FlipDiagonal
float2 c0;
float2 c1;
#endif

float4 main(float2 tex : TEXCOORD0) : COLOR
{
tex -= .5;
#if FlipDiagonal
float2 geometryswap = c1*c0.yx;
float2 border = .5*geometryswap;
if((abs(tex.x) > border.x) || (abs(tex.y) > border.y)) return BackgroundMask;// draw background color on background pixels
#endif
#if FlipHorizontal && FlipVertical
tex = -tex;
#elif FlipHorizontal
tex.x = -tex.x;
#elif FlipVertical
tex.y = -tex.y;
#endif
#if FlipDiagonal
tex = tex.yx*geometryswap;
#endif
return tex2D(s0, tex+.5);// sample and output
}

romulous
1st January 2014, 04:28
Yes, thanks - that seems to remove the artifacts pretty well. It's much appreciated - you make writing these things look so easy! :) Is how 'heavy' the shader is based on your video card, or video card+cpu, or overall system?

I think Blight was wondering what pixel shader profile was required - is that the "ps_2_0" listed in the header?

JanWillem32
1st January 2014, 05:55
This shader really isn't that heavy compared to complex filters, such as some forms of resizeing, debanding, denoising, sharpening and frame interpolating types (and it was indeed really easy to write as well). An old, low-end GPU/IGP might choke on executing this shader in some cases, but setting a few shaders is usually not really a problem in most cases. This particular shader indeed requires the Direct3D 9 minimum of PS 2.0 support from the GPU, as indicated. Not that it really matters, as a video renderer can simply auto-detect ps_2_0, ps_2_a, ps_2_b and ps_3_0 levels from the D3D9 support caps report and use the highest level available. If a shader fails, that particular shader's title can simply be reported back to the user (already a required feature, as a video renderer supporting custom shaders has to deal with truely faulty shaders as well). There are also not that many active users using a GPU with lower than PS 3.0 (and PS 2.0 or higher) support anymore.
For MPC-HC I've advised some time ago to no longer even store the pixel shader compiling level with every shader. The interface to the video renderers doesn't need this parameter at all. The pixel shader menus can simply default to PS 3.0 every time, and offer the other three modes for testing purposes only.
For MadVR the case is even easier. MadVR notes in the list of system requirements "graphics card with full D3D9 / PS3.0 hardware support". There is no use in compiling pixel shaders at a lower level than that.

James Freeman
1st January 2014, 11:44
@JanWillem32

Can you please make "Sharpen Complex 2" only for Chroma?

I am on to something big here (huge improvement to chroma upscaling resolution).
I can almost make 4:2:0 to look like 4:4:4.


I'll explain:

First I captured a Belle-Nuit (http://www.belle-nuit.com/test-chart) test chart in 4:4:4 (rgb32) video.
Then I ran it through x264 to make a 4:2:0 video (and lose chroma information).
Then I opened both videos side by side and activated your pixel shader called "chroma for SD&HD video input" to show only chroma information on both of them.
Then I activated "sharpen complex 2" (pre-resize) on the 4:2:0 video and carefully tweaked it look like the 4:4:4 video (yes, it can even do that).

The idea is quite simple: Sharpen the chroma before upscaling.
The Sharpen 4:2:0 chroma results are very nice, almost like the original 4:4:4 (giving the saturated colors back to high frequency details).
Now I only need to put the Sharpen Chroma together with the untouched Luma for a perfect 4:2:0 -> 4:4:4 conversion.
That's why I need the Sharpen Complex 2 only for Chroma, leaving the Luma untouched.

Hope that captures you interest.

Happy New Year !

XRyche
1st January 2014, 12:33
@JanWillem32: I'm quite sure you won't be interested, but maybe curiosity will persuade you.

Samsung TV offers a setting called "Dynamic Contrast" in options (not "CE dimming"), which changes original image, but I find it to be "nice looking" sometimes. You have 3 settings, but "low" is the best, 2 others change image too much.

Do you think you could write a shader for this, or it would me more complicated for the GPU ?
I suppose it changes pixel like this:
(post-resized by renderer)
Old Pixel: R=50; G=40; B=230
New Pixel:
R= 50+((50-128)*5%) = 46 (rounded)
G= 40+((40-128)*5%) = 36 (rounded)
B= 230+((230-128)*5%) = 235 (rounded)

Do you think my reasoning is stupid ?:confused:
Is there a simple way to test this algorithm with MPC ?

Just as JanWillem32 suggested use his CIECAM02 shaders. If for example your movies appear too dark (to the point of even losing some detail in dark ambiance and/or night-time scenes) and lowering gamma just washes everything out than the CIECAM02 shaders using the "average""User Settings" are for you. Just try them, they will pleasantly surprise you.

pirlouy
1st January 2014, 19:40
AFAIK the dynamic contrast option works by measuring ambient light in one's room so I guess it's impossible to simulate it correctly using shaders alone.
My TV does not have any sensor like this; it really is a modification with a precise algorithm.

@JanWillem32: Your example code works well. But what are those CIECAM02 shaders you're talking about ? I tried to search but did not find/understand what it is or where to download these shaders ? :/

JanWillem32
2nd January 2014, 03:10
James Freeman, many chroma up-sampling and other resizing methods already have sharpening internally. Modifying any sharpening factors on these is easy. The sharpest chroma up-samplers (I implemented several) are not always the best-looking though. The sharpness factors are just one part of good scaling. What processing chain did you use for this test? It's possible that all you want is a different chroma upsampler.

pirlouy, "dynamic contrast" just compresses image dynamics or changes gamma without using much logic. Using "precise algorithm" to describe such an effect is quite an overstatement.
The CIECAM02 transforms were already integrated in the EVR-CP/VMR9 r. color management options I helped to integrate. For the new basic color correction option I added, there is no such option yet. I wrote a separate pixel shader before integrating it into newer builds to test the function. See for reference: http://forum.doom9.org/showthread.php?p=1658826#post1658826 .

James Freeman
2nd January 2014, 07:06
James Freeman, many chroma up-sampling and other resizing methods already have sharpening internally. Modifying any sharpening factors on these is easy. The sharpest chroma up-samplers (I implemented several) are not always the best-looking though. The sharpness factors are just one part of good scaling. What processing chain did you use for this test? It's possible that all you want is a different chroma upsampler.

Jan

I use MadVR Lanczos/Jinc for chroma upscaling but even that is not sharp enough for what I have in mind.
The goal of this experiment is to make the 4:2:0 chroma look like 4:4:4 chroma which is a lot sharper an more saturated.

I simply want to have control over the sharpness of the chroma, and "Sharpness Complex 2" is the best in my taste.

I can make a short video to demonstrate what I have done so far.

EDIT:

Here is a short video where I compare 4:4:4 vs 4:2:0 vs 4:2:0+Sharpen: Chroma Sharpen Demo (http://www.mediafire.com/watch/plaj4kh59zv8jpg/Chroma%20Sharpen%20Demo.avi)
*Its a screen capture, 28MB uncompressed rgb32.
*Please download the original video (don't watch online => quality destroyed).

The upscaler in the video is MadVR's Lanczos 3+AR which is not sharp enough.

There are two presets that I use in this video.
Chroma Only: Shows just the chroma.
Chroma Sharpen: Shows just chroma + Sharpen Complex 2 (Pre-Upscaler/resize).
*Placing the Sharpen after-upscaling does not have the same effect!!
*Note that the The Sharpen Complex 2 is carefully tweaked to look like 4:4:4 and not at it default settings.

Look at the green lines as they become more vibrant like in the original 4:4:4.
Look at the red/cyan fine lines as they become more distinct and colorful like in the original 4:4:4.
You can clearly see that 4:2:0+Sharpen looks a lot closer to the original 4:4:4.

Leaving the Luma untouched to prevent ringing and artifacts, just a better looking, more "True to the Source" chroma.


EDIT 2:

An even clearer video of this "trick"
Chroma Sharpen Demo 2 (http://www.mediafire.com/watch/yzozc6mb7ujxcbo/Chroma%20Sharpen%20Demo%202.avi)

Here you can clearly see that sharpening the chroma makes "magic" in fine details, almost recreating the missing data.

Thanks for your time.

XRyche
2nd January 2014, 09:59
My TV does not have any sensor like this; it really is a modification with a precise algorithm.

@JanWillem32: Your example code works well. But what are those CIECAM02 shaders you're talking about ? I tried to search but did not find/understand what it is or where to download these shaders ? :/

The shaders are located in 2 text documents in the compressed file (.7z) Of JanWillem32's latest build of his renderer found here: http://forum.doom9.org/showthread.php?t=161047 . At the bottom of the very first post.

toniash
2nd January 2014, 14:03
The shaders are located in 2 text documents in the compressed file (.7z) Of JanWillem32's latest build of his renderer found here: http://forum.doom9.org/showthread.php?t=161047 . At the bottom of the very first post.

What's the name of the shaders? I can't find them ...

JanWillem32
2nd January 2014, 14:07
James Freeman, what exact processing chain did you use? When feeding textures containing Y'CbCr into the "Sharpen Complex 2" shader it does not exclude the Y' channel without modifications.
Also note that Lanczos filtering is sharp, but it's not the sharpest resizer. There are other options that sharpen more, but as expected, these give heavy artifacts.

James Freeman
2nd January 2014, 15:11
Jan,

My chain in MPC-HC:
http://www.mediafire.com/convkey/b68f/n6svgk5389vsghyfg.jpg

There is no luma in those videos, just chroma.
That is why I ask you for help.
There is currently no sharpen shader only for chroma.

We need something that will divide Y from CbCr, and only apply sharpening to CbCr then combine them to YCbCr again without touching the Y.

Lanczos filtering is sharp, but it's not the sharpest resizer. There are other options that sharpen more, but as expected, these give heavy artifacts.
Lanczos is the sharpest resizer in MadVR (to my eyes), but not sharp enough.
Thats why I use Sharpen Complex 2, to carefully sharpen the chroma image without adding unwanted artifacts.
But as stated, there is no way currently to combine back my chain with the removed Y (luma) and the already sharpen chroma.

JanWillem32
2nd January 2014, 23:34
That actually explains a lot. "chroma for SD&HD input" is a test shader. It converts R'G'B' to YCbCr, discards original luma, multiplies chroma by 1.5 (to make it more visible), and converts back to R'G'B' with the Y' channel fixed at .5. The output isn't chroma, but just weird R'G'B'. To get real Y'CbCr, use a "R'G'B' to Y'CbCr"-type shader. You can then really filter chroma. I've already written Y'CbCr filtering shaders. Doing any filtering in Y'CbCr is risky. The Y'CbCr forms don't directly specify any color; all specifications are dependent on R'G'B'/RGB color space (which in turn has specifications in XYZ color space and a reference surround specification). In the category of "everyday-use effect pixel shaders" I only made chroma up-sampler shaders and the deband/denoise/sharpen effect shaders for now. (That last effect is only to deal with encoder noise and bad raw image quantization, these are really not suitable for any dramatic effects.)
When I think of effects to compensate anything of a resizer, it will probably be completely dependant as a compensation factor for a specific resizer, and also be integrated into that resizer as well. Chroma up-samplers are essentially resizers, with pretty much the same problems.
As for sharper resizers than Lanczos, there are a few bicubic variants that you might like to try. I'm not sure any of those are integrated in madVR. (I'm also not too sure that these would be really useful as well.)

James Freeman
3rd January 2014, 14:56
Jan,

If I understood you correctly, to sharpen only the chroma, this chain is necessary:

1. R'G'B' to Y'CbCr.
2. CbCr Sharpen Complex 2 (chroma only)
3. Y'CbCr to R'G'B'.

If so,
Is there any way to do #2 with any of the current shaders?


I also modified the "Chroma for SD&HD video input" shader to show only pure chroma (0.5=>0 & 1.5->1.0).
The image looks Black, Red & Blue (as expected).

Now I have tweaked the Sharpen shader even more accurately.
It looks even closer to 4:4:4 now., almost identical.

Jan,
How hard will it be to insert a "Sharpen Complex 2" to only affect the CbCr data into the above 1,2,3 chain,
and make a single Shader that does this?

JanWillem32
4th January 2014, 03:21
That chain is correct. To simplify it for other Y'CbCr-type shaders, I've merged the Y'CbCr to R'G'B' step (and onward standard color transforms) into the previous shader for some of the chains I designed earlier. The first shader is better off being separate, as the next step takes multiple samples. (If a shader takes only one sample, you can always merge it with the previous shader. Even merging several shaders is possible.)
The shaders for Y'CbCr I've already written are chroma up-samplers and the deband/denoise/sharpen effects. Both have sharpening to partiallly compensate some of the base problems of the main filter.
'Simple' sharpening filters are useful for raw, high-quality video and images straight from the camera, in a decent color space, to compensate for areas that should be more in the foreground, but seem a bit 'weak' (determined by the person that does the mastering).
I see no place for such 'simple' sharpening outside of that context. The various Y'CbCr forms are only used to encode color, and you need some filters in Y'CbCr stages to filter some of the encode's problems and later on convert it to R'G'B'. However, Y'CbCr does a terrible job at actually describing a uniform or human vision-relative color space. Every flaw in a mixer's/renderer's Y'CbCr filtering stages becomes amplified a lot in terms of visible artifacts. You can't really do much with it in filters directly.

vood007
4th January 2014, 09:31
Jan, is it possible to have a single color plane with a fixed size in the background and the actual video centered on top of it? In other words; When the player window is bigger than the video and scaling is turned off, the video is obviously surrounded by a black frame. Can we fill this frame with a color other than black?

JanWillem32
4th January 2014, 22:39
If an interface allows you to set a background color in the video renderer, it's easy. I implemented such a function a while ago for the renderers I edit (miscellaneous tab). For the cases that require a special approach, use the "letterbox" and "pillarbox" shaders.

toniash, sorry for the late response. I simply overlooked your question earlier. The CIECAM02 shaders are included along with the five tester builds at the bottom of the first post of that other thread. (It's not included with the source code archive.)

vood007
5th January 2014, 20:22
If an interface allows you to set a background color in the video renderer, it's easy. I implemented such a function a while ago for the renderers I edit (miscellaneous tab). For the cases that require a special approach, use the "letterbox" and "pillarbox" shaders.

What you added to the misc tab of your study build is exactly what i want, so how do we get this into main MPCHC branch?

JanWillem32
6th January 2014, 00:47
Sorry, but I don't edit the video renderers in the main branch anymore. The mixer classes part of the internal renderers (VMR-9 r., EVR CP, RealMedia DX9, Quicktime DX9) and the two renderer sockets were reasonably well-written, so only had to modify those. The main renderer is beyond salvation. I tried to modify it at first. Some of the simple patches I made a few years ago worked well, so these were integrated. When I tried to edit more parts, disaster on disaster followed. Once I finally had enough I decided to no longer edit it. I integrated a renderer I wrote/edited earlier that worked and got rid of the old one. It broke pretty much all compatibility with the old code parts. It took weeks for it to compile, and a bit longer to run well. I'm very satisfied with the results. I even integrated some complicated functions without too much of a hassle. The main branch renderer and the one I wrote are similar in settings and menus, and I didn't sacrifice original functionality (although I'd rather not have transplanted the original "VSync" functions). However, I still modified several megabytes of code. Integration will not be easy. Smaller parts of the code can go in the main branch without a problem as patches. The main renderer change and all of its functionality will be one huge patch.

vood007
6th January 2014, 01:55
Not a big problem, theres still good old FFDShow. Anyway thanks for answering.

turbojet
7th January 2014, 08:03
James Freeman: Defining chroma coefficients in the developer section of lumasharpen shader (http://dropcanvas.com/l46x9) to sharpen only chroma. It sharpens much like sharpen complex 2 but with less edge artifacts.

James Freeman
10th January 2014, 19:17
James Freeman: Defining chroma coefficients in the developer section of lumasharpen shader (http://dropcanvas.com/l46x9) to sharpen only chroma. It sharpens much like sharpen complex 2 but with less edge artifacts.

Thanks.

Can you please guide me how to do this?

I tested the MPC Luma Sharpen and its very nice !!

turbojet
11th January 2014, 01:04
I don't know the chroma coeffecients, maybe someone else does?

I think just this line needs to be commented and insert a new line around it.
#define CoefLuma float4(0.2126, 0.7152, 0.0722,0)

Unrelated but there's an interesting comment that might be worth trying for someone with the knowledge. // -- Clamping the maximum amount of sharpening to prevent halo artifacts --
sharp_luma = clamp(sharp_luma, -sharp_clamp, sharp_clamp); //TODO Try a curve function instead of a clamp

James Freeman
11th January 2014, 17:20
JanWillem32,

I have been using a small avisynth script to create Black Frame Insertion to see how a video looks without motion blur.
I looks fantastic (leaving the flicker aside) !!
But it takes huge amount of memory and is non fluid (stutters).

Is it possible to write a simple shader that replaces 1 or 2 black frames after each refresh rate?

for example:
72Hz monitor.
1, B, B, 4, B, B, 7, B, B, 10, B, B etc... to 72.
The goal is to show only One out of Three frames.
or
1, 2, B, 4, 5, B, 7, 6, B, 10, 11, B etc... to 72.
show only 2 out of 3 frames.

This way after each movie frame (24fps) the display will show 1 or 2 black frames to eliminate motion blur.
There is no need to take the movie frame rate into consideration, only the monitor refresh rate.

It also will be nice if the shader can automatically read the display refresh rate, or let the user select how much black frames to insert after how much normal frame/s.
Of course it should be in-sync with the monitor refresh rate.

Are you familiar with Backlight Strobing or BFI?

nevcairiel
11th January 2014, 17:36
Shaders work on a given image, I don't think they can produce new images.

JanWillem32
11th January 2014, 21:16
Correct, this is more a task for an internal renderer routine. A pixel shader can change entire frames into solid colors or gradients, and with some temporal effects using the frame and time counters, but actually presenting more output frames per second has to be done by the host renderer.
I can easily (temporarily) add this function to the 'Alternative Scheduler' renderer function (requires Vista or newer) for the renderer I'm editing if you just want to test a more lightweight solution than using Avisynth for this case.
As for these presenting techniques, some parts are easy, some are not:
-Setting a frame to black before presenting it is very easy.
-Setting the amount of refreshes for a presented frame is not supported under XP, handled by a nasty function under Vista in windowed mode and can be handled normally under 7 and newer in windowed mode, plus under Vista and newer in D3D full-screen exclusive mode.
-Frame-time, jitter and other presentation statistics requires managing a lot of code.
-The frame time stamps of incoming video source frames are unreliable. The average over a lot of frames does add up nicely to a frame-time clock, but individual time stamps will often be off by several milliseconds. That means that a renderer has to estimate for how long a frame should be presented, and then also implement scheduling for getting a matching input frame rate to display refresh rate. All of this stuff is also implemented along with the statistics parts, as you always have to compensate for jitter and imprecision of timing data in the long run.
-Getting the monitor refresh rate is difficult. The pixel clock of the video card is actually really stable, but most software interfaces (even the ones that seem to have decent precision) report its rate incorrectly. The few that do work have low precision and will fail sometimes.
-The video renderer runs its main loop for every incoming frame (and once in a while for a repeated frame in paused mode). The the display refresh rate only comes into play with presenting after the scheduling functions/constant frame interpolator correlated it with the video frame rate (with compensation). It really doesn't work the other way around.
All in all, the various presentation functions usually take a lot of code to handle. Black frame insertion is easy to add to the 'Alternative Scheduler' renderer function, because of its method. Backlight strobing has to be handled by the hardware of the display device. The data stream from the source device doesn't include such a control.

James Freeman
11th January 2014, 23:00
Thanks Jan.

I can see its a big hassle, so never mind.

I've played enough with avisynth BFI to be convinced of this effect.
I think I should buy a proper Backlight Strobing monitor.

Though, till an IPS panel with 120Hz and backlight strobing will exist, I'm waiting.

JanWillem32
17th January 2014, 02:26
I was asked to improve the quality of the sphere shader, so I did a bit of work on the version I already edited. It's a bit more complicated, so it takes a lot more instructions compared to the original, but it's worth it.
If someone can help a bit with the old cinema film grain effect shader with colorimetry data of silver grains, sepia toning and such, or with documented methods that could help (that don't use external textures), I would appreciate it. I'm a bit stuck at getting significantly better results from prototype shaders compared to the already available shaders unfortunately. I had to guess a lot of variables, so that's one of the problems. Another problem is getting multiple grain sizes on screen, with decent randomness.// (C) 2011-2014 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// sphere, Catmull-Rom spline4×4 interpolated
// This shader should be run as a screen space pixel shader if you are up-scaling.
// This shader should not be run as a screen space pixel shader if you are down-scaling.
// This shader requires compiling with ps_2_a, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// This shader is meant to work with linear RGB input and output. Regular R'G'B' with a video gamma encoding will have to be converted with the linear gamma shaders to work properly.
// Use this shader to apply an effect that looks like projecting the video from a rotating sphere.

// fractions, either decimal or not, are allowed
// rotation speed, in rotations per second
#define rs .125
// border canvas size
#define bs 7.75
// border gamma factor
#define bf 128.
// light position
#define pl float3(6., -6., -7.)
// light intensity
#define cl .5
// light size
#define sl 64.
// camera position
#define pc float3(0., 0., -1.)
// sphere position
#define ps float3(0., 0., .75)
// sphere radius
#define ra acos(-1.)*.25
// base size constant
#define Ai 1.

sampler s0;
float4 c0 : register(c0);
float2 c1 : register(c1);
#define sp(a, b, c) float3 a; {float2 tmp = tex+c1*float2(b, c); a = tex2D(s0, frac(abs(float2(tmp.x, abs(tmp.y)*-1.+1.)))).rgb;}

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float ar = c0.x*c1.y;// aspect ratio
tex.x = tex.x*ar+.5-.5*ar;// surface rectangle to square
// relate the sphere to the camera position
float3 pd = normalize(float3(tex.xy-.5, 0.)-pc);
float B = dot(pd, 2.*(pc-ps));
float C = dot(pc-ps, pc-ps)-pow(ra, 2);
float D = B*B-4.*Ai*C;// calculate the sphere
if(D < 0.) return 0.;// output black borders, only map if things are inside the sphere

// intersection data
float3 p = pc+pd*(-sqrt(D)-B)*.5/Ai;
float3 n = normalize(p-ps);
float3 l = normalize(pl-p);

float2 cd = .75*(.5-tex);// measure the distance to the image center
tex = acos(-n.xy)/acos(-1.);// mapping the image onto the sphere
tex.x = frac(tex.x+c0.w*rs);// rotation
tex.y = (tex.y-.5)*ar-.5;// aspect ratio correction
tex *= c0.xy;// normalize to texture size in pixels
float2 t = frac(tex);// calculate the difference between the output pixel and the original surrounding two pixels
tex = (tex-t+.5)*c1+float2(1., 0.);// make the sampling position line up with an exact pixel coordinate for L1, normalized to the interval (1, 2), not (0, 1) as we want texture wrapping in this case

// weights
float2 t2 = t*t, t3 = t2*t;
float4 w13 = t3.xyxy*float2(1.5, .5).xxyy+t2.xyxy*float2(-2.5, -.5).xxyy;
float4 w02 = t3.xyxy*float2(-.5, -1.5).xxyy+t2.xyxy*float2(1., 2.).xxyy+t.xyxy*float2(-.5, .5).xxyy;
w13.xw += 1.;

// original pixels
sp(L0, -1., -1.) sp(L1, -1., 0.) sp(L2, -1., 1.) sp(L3, -1., 2.)
sp(K0, 0., -1.) sp(K1, 0., 0.) sp(K2, 0., 1.) sp(K3, 0., 2.)
sp(J0, 1., -1.) sp(J1, 1., 0.) sp(J2, 1., 1.) sp(J3, 1., 2.)
sp(I0, 2., -1.) sp(I1, 2., 0.) sp(I2, 2., 1.) sp(I3, 2., 2.)

// vertical interpolation
float3 Q0 = L0*w02.y+L1*w13.y+L2*w02.w+L3*w13.w;
float3 Q1 = K0*w02.y+K1*w13.y+K2*w02.w+K3*w13.w;
float3 Q2 = J0*w02.y+J1*w13.y+J2*w02.w+J3*w13.w;
float3 Q3 = I0*w02.y+I1*w13.y+I2*w02.w+I3*w13.w;
float3 P0 = Q0*w02.x+Q1*w13.x+Q2*w02.z+Q3*w13.z;// horizontal interpolation

return ((P0+cl*pow(max(dot(l, reflect(pd, n)), 0.), sl))*min(pow(bs*dot(cd, cd), -bf), 1.)*dot(n, l)).rgbb;// add specular mapping, sphere edges, diffuse mapping and then output
}// (C) 2011-2014 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// sphere, Catmull-Rom spline4×4 interpolated on 16-bit integer surfaces
// This shader should be run as a screen space pixel shader if you are up-scaling.
// This shader should not be run as a screen space pixel shader if you are down-scaling.
// This shader requires compiling with ps_2_a, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// This shader is meant to work with linear RGB input and output. Regular R'G'B' with a video gamma encoding will have to be converted with the linear gamma shaders to work properly.
// Use this shader to apply an effect that looks like projecting the video from a rotating sphere.

// fractions, either decimal or not, are allowed
// rotation speed, in rotations per second
#define rs .125
// border canvas size
#define bs 7.75
// border gamma factor
#define bf 128.
// light position
#define pl float3(6., -6., -7.)
// light intensity
#define cl .5
// light size
#define sl 64.
// camera position
#define pc float3(0., 0., -1.)
// sphere position
#define ps float3(0., 0., .75)
// sphere radius
#define ra acos(-1.)*.25
// base size constant
#define Ai 1.

sampler s0;
float4 c0 : register(c0);
float2 c1 : register(c1);
#define sp(a, b, c) float3 a; {float2 tmp = tex+c1*float2(b, c); a = tex2D(s0, frac(abs(float2(tmp.x, abs(tmp.y)*-1.+1.)))).rgb;}

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float ar = c0.x*c1.y;// aspect ratio
tex.x = tex.x*ar+.5-.5*ar;// surface rectangle to square
// relate the sphere to the camera position
float3 pd = normalize(float3(tex.xy-.5, 0.)-pc);
float B = dot(pd, 2.*(pc-ps));
float C = dot(pc-ps, pc-ps)-pow(ra, 2);
float D = B*B-4.*Ai*C;// calculate the sphere
if(D < 0.) return 0.;// output black borders, only map if things are inside the sphere

// intersection data
float3 p = pc+pd*(-sqrt(D)-B)*.5/Ai;
float3 n = normalize(p-ps);
float3 l = normalize(pl-p);

float2 cd = .75*(.5-tex);// measure the distance to the image center
tex = acos(-n.xy)/acos(-1.);// mapping the image onto the sphere
tex.x = frac(tex.x+c0.w*rs);// rotation
tex.y = (tex.y-.5)*ar-.5;// aspect ratio correction
tex *= c0.xy;// normalize to texture size in pixels
float2 t = frac(tex);// calculate the difference between the output pixel and the original surrounding two pixels
tex = (tex-t+.5)*c1+float2(1., 0.);// make the sampling position line up with an exact pixel coordinate for L1, normalized to the interval (1, 2), not (0, 1) as we want texture wrapping in this case

// weights
float2 t2 = t*t, t3 = t2*t;
float4 w13 = t3.xyxy*float2(1.5, .5).xxyy+t2.xyxy*float2(-2.5, -.5).xxyy;
float4 w02 = t3.xyxy*float2(-.5, -1.5).xxyy+t2.xyxy*float2(1., 2.).xxyy+t.xyxy*float2(-.5, .5).xxyy;
w13.xw += 1.;

// original pixels
sp(L0, -1., -1.) sp(L1, -1., 0.) sp(L2, -1., 1.) sp(L3, -1., 2.)
sp(K0, 0., -1.) sp(K1, 0., 0.) sp(K2, 0., 1.) sp(K3, 0., 2.)
sp(J0, 1., -1.) sp(J1, 1., 0.) sp(J2, 1., 1.) sp(J3, 1., 2.)
sp(I0, 2., -1.) sp(I1, 2., 0.) sp(I2, 2., 1.) sp(I3, 2., 2.)

// vertical interpolation
float3 Q0 = L0*w02.y+L1*w13.y+L2*w02.w+L3*w13.w;
float3 Q1 = K0*w02.y+K1*w13.y+K2*w02.w+K3*w13.w;
float3 Q2 = J0*w02.y+J1*w13.y+J2*w02.w+J3*w13.w;
float3 Q3 = I0*w02.y+I1*w13.y+I2*w02.w+I3*w13.w;
float3 P0 = Q0*w02.x+Q1*w13.x+Q2*w02.z+Q3*w13.z;// horizontal interpolation

return ((P0*65535./32767.-16384./32767.+cl*pow(max(dot(l, reflect(pd, n)), 0.), sl))*min(pow(bs*dot(cd, cd), -bf), 1.)*dot(n, l)*32767./65535.+16384./65535.).rgbb;// add specular mapping, sphere edges, diffuse mapping and then output
}

romulous
31st January 2014, 13:58
Hi JanWillem32,

Blight is doing some work to integrate the rotation shader you wrote on page 20 into Zoom Player. He just had a couple of questions he wanted me to ask you if you don't mind. Some quoted text first, and then the question afterwards.

Question #1:

Note that geometry changes due to rotation usually require manual compensation, as the video renderer host usually doesn't compensate for it automatically.

Where does the manual compensation have to be performed?

Question #2:

// Note than when enabling diagonal flipping, the resizing factor has to be lowered in advance to allow the full image to be visible.

Where do you set the resize factor?

Thanks!

hadi79
31st January 2014, 18:10
Hi guys,

Could anyone help me?

Why this shader doesn't work on my MPC?
This is the error: error X3507: 'main': Not all control paths return

link (http://dl.dropboxusercontent.com/s/fh3mqtqcylhe2r4/discman.txt)

JanWillem32
1st February 2014, 02:40
hadi79, I don't see why that shader wouldn't compile. It could use a few changes, though. Change "static float" to "static const float", as it's a compile-time constant. Change "1.0f" to "1.0" or "1.", as the 'f' or 'F' suffixes are considered to be bad style when working with HLSL. Change "#define BlockCount 75" to "#define BlockCount 75.0" or "#define BlockCount 75.", as it's never used as an integer. The HLSL compiler doesn't reliably do implicit type casts when compiling. Always specify floating-point values as floating-point or use explicit type casts. (I really think all C, C++ and HLSL compilers should should warn about all implicit type casts.)
The effect itself is actually quite a funny one. It's pretty basic, though. (It doesn't pre-process with a low-pass, nor does it apply anti-aliasing on its mask.)

If PS 3.0 code isn't a problem, you can also add branching to optimize out the sampling of the zero-value output pixels:#define BlockCount 75.
#define Min .2
#define Max .45
sampler2D input : register(S0);

// static constants used as optimization
static const float BlockSize = 1./BlockCount;

float4 main(float2 uv : TEXCOORD) : COLOR
{
// Calculate block center
float2 blockPos = floor(uv*BlockCount);
float2 blockCenter = blockPos*BlockSize+BlockSize*.5;

// Round the block by testing the distance of the pixel coordinate to the center
float dist = length(uv-blockCenter)*BlockCount;
[branch] if(dist < Min) {
return 0.;}
else if(dist > Max) {
return 0.;}
else {// Sample color at the calculated coordinate
return tex2Dlod(input, float4(blockCenter, 0., 0.));}
}
romulous, setting the resizing factor is usually handled by the host player. Most video renderers do have a default setting which just resizes video to the full window size plus letterboxing/pillarboxing it to maintain the intended aspect ratio of the video source.
For standard interfaces to renderers there are these calls:
EVR/MF interface control:
IMFVideoDisplayControl::SetVideoPosition()
Standard DirectShow interface controls:
IBasicVideo::SetDefaultSourcePosition()
IBasicVideo::SetDestinationPosition()
IBasicVideo also has a lot of other calls to handle input/output video size for a video renderer
IVideoWindow::SetWindowPosition()
IVideoWindow also has a few other calls to handle the state of the presentation window

The EVR also natively supports rotation, but I've never worked with that, so I don't know how it behaves.

As for resizing factors, if you take the simple example of a 1920×1080 image on a 1920×1080 window without resizing or repositioning, your source and destination rectangles will simply be {0, 0, 1920, 1080}, {0, 0, 1920, 1080} (left, top, right, bottom).
When you use diagonal flipping and you intend to keep the image in the same aspect ratio, the destination rectangle will have to change. For this case {420, 0, 1500, 1080} would be suitable if you want a centered image. (That's a resizing factor of 9./16..)

For the case of a DirectX 9 renderer that you can edit, you can just set different vertices. (Note that when you can edit vertices, you don't need the rotation shader at all.)
Example for a very basic FVF-style (D3DFVF_XYZRHW | D3DFVF_TEX1) pre-transformed vertex statement in a top-left, top-right, bottom-left, bottom-right index order:struct CUSTOMVERTEX_TEX1 {
float x, y, z, rhw, u, v;
};
float hres = 1920.f, vres = 1080.f;
// lists for DrawIndexedPrimitive() or DrawPrimitive()
// standard
CUSTOMVERTEX_TEX1 v[4] = {
{ -.5f, -.5f, 0.f, 1.f, 0.f, 0.f},
{hres-.5f, -.5f, 0.f, 1.f, 1.f, 0.f},
{ -.5f, vres-.5f, 0.f, 1.f, 0.f, 1.f},
{hres-.5f, vres-.5f, 0.f, 1.f, 1.f, 1.f}};
// flipped horizontally
CUSTOMVERTEX_TEX1 v[4] = {
{hres-.5f, -.5f, 0.f, 1.f, 0.f, 0.f},
{ -.5f, -.5f, 0.f, 1.f, 1.f, 0.f},
{hres-.5f, vres-.5f, 0.f, 1.f, 0.f, 1.f},
{ -.5f, vres-.5f, 0.f, 1.f, 1.f, 1.f}};
// flipped vertically
CUSTOMVERTEX_TEX1 v[4] = {
{ -.5f, vres-.5f, 0.f, 1.f, 0.f, 0.f},
{hres-.5f, vres-.5f, 0.f, 1.f, 1.f, 0.f},
{ -.5f, -.5f, 0.f, 1.f, 0.f, 1.f},
{hres-.5f, -.5f, 0.f, 1.f, 1.f, 1.f}};
// flipped horizontally and vertically
CUSTOMVERTEX_TEX1 v[4] = {
{hres-.5f, vres-.5f, 0.f, 1.f, 0.f, 0.f},
{ -.5f, vres-.5f, 0.f, 1.f, 1.f, 0.f},
{hres-.5f, -.5f, 0.f, 1.f, 0.f, 1.f},
{ -.5f, -.5f, 0.f, 1.f, 1.f, 1.f}};
// note: diagonal flipping requires adaption of the input-to-output resolution
// flipped diagonally over the top-left-to-bottom-right axis
CUSTOMVERTEX_TEX1 v[4] = {
{ -.5f, -.5f, 0.f, 1.f, 0.f, 0.f},
{ -.5f, vres-.5f, 0.f, 1.f, 1.f, 0.f},
{hres-.5f, -.5f, 0.f, 1.f, 0.f, 1.f},
{hres-.5f, vres-.5f, 0.f, 1.f, 1.f, 1.f}};As a last note, the IDirect3DDevice9::StretchRect() function can do nearest neighbor and bilinear image resizing, but does not support rotation. A call to DrawIndexedPrimitive() or DrawPrimitive() on a correctly configured device, with optionally a resizing shader enabled for that stage is required for rotation.

hadi79
1st February 2014, 15:12
Thanks for your help. JanWillem32

hadi79
1st February 2014, 15:26
Thanks for your help. JanWillem32

JanWillem32
2nd February 2014, 20:07
You're welcome. If you need any help with other filtering code, such as the low-pass or anti-aliasing effects I mentioned, I'm happy to help.

romulous
7th February 2014, 09:11
Jan-Willem: Many thanks for your response to my questions from Blight - he has made some progress in integrating the script into Zoom thanks to your help :)

Regards,

romulous

romulous
12th February 2014, 07:55
Hi again Jan-Willem,

Blight had a follow-up question regarding the rotation shader. He isn't sure if you can compensate for the cropping like you described previously. He has tried, but he believes the actual content is cropped and is therefore not accessible to the video renderer. He wanted me to ask you using ibasicvideo/ivideowindow, how to make it work if the source video resolution is1920x1080 (for example, what values to pass the ibasicvideo/ivideowindow interfaces).

Regards,

romulous

JanWillem32
12th February 2014, 11:49
I just reviewed the rotation shader again. I added the comment "// This shader shoud be run as a screen space pixel shader when enabling diagonal flipping, else both modes will work.", but that's actually not entirely correct. If the resizer section clips the input video rectangle before the rotation (common when down-sizing), a part of the input is lost. In such a case, the rotation shader can be inserted before resizing.
Note that there's no proper way to compensate if you need down-sizing in one direction and up-sizing in another. Also, positioning the input on the output rectangle can cause clipping in the resizing section as well. However, if you edit the vertices of the resizing section like I described before, none of these problems occur.

romulous
12th February 2014, 12:19
Thanks - this implementation is using madVR, which does not allow access to the vertices as far as Blight knows. I think that means we are stuck until madshi adds rotation support to madVR?

JanWillem32
12th February 2014, 14:51
I think you are correct.

leeperry
26th March 2014, 18:45
Hi Jan, would that be possible to align MPEG1 to look like MPEG2/H264 chroma via a PS script?

mVR only does MPEG2/H264 chroma alignment so this would be very handy.

I was under the impression that outputting YUY2 from ffdshow would align chroma properly but I ain't too sure anymore, I guess only AYUV & Y416 would do what I want?

Anyway, PotPlayer's seamless playback feature likes to crash randomly when not using its built-in decoders so that doesn't really solve anything :o

:thanks: for your help,

JanWillem32
27th March 2014, 13:52
Do you mean chroma cositing? http://msdn.microsoft.com/en-us/library/windows/desktop/ms694252%28v=vs.85%29.aspx
It's part of the standard of how to convert Y'CbCr to R'G'B'. The pixel shader stages accessible by the user are already R'G'B' or onward, and there's no real way to convert back if it was handled in the wrong way. I think it's best to just wait for the renderer to be fixed. I implemented support for both common forms of chroma cositing a few months ago. It's really not that hard to implement.

leeperry
27th March 2014, 15:53
HI Jan, thanks for the reply.

From http://bengal.missouri.edu/~kes25c/ddcc.zip\ddcc - ReadMe.txt
cplace -

Specifies horizontal chroma placement... used when input is yuy2. Possible settings:

0 - chroma is aligned with left pixel in each pair (mpeg2, mpeg4, h264)

1 - chroma is centered between each pair of pixels (h261, h263, mpeg1)

default: 0

I do realize that it'll require some work considering that PS scripts work in RGB, but Leak wrote a script to smooth chroma (http://forum.doom9.org/showpost.php?p=1184975&postcount=32) so it still should be possible? Or not? :o

What I would need is a PS script that would align MPEG1 chroma like MPEG2 so mVR would align it properly afterwards, basically a PS script of one of those scripts: http://avisynth.nl/index.php/External_filters#Chroma_correction
ChromaShiftSP : This script can shift chroma in all directions with subpixel accuracy.

Humm, so forcing AYUV/Y416 output from ffdshow is the only way to overcome the problem?

nevcairiel
27th March 2014, 17:10
Humm, so forcing AYUV/Y416 output from ffdshow is the only way to overcome the problem?

That is assuming ffdshow even does it correctly, especially when it comes to the 16-bit formats I wouldn't really trust it.

foxyshadis
28th March 2014, 02:18
No, forcing any output won't change anything, except RGB output. (ffdshow will sample chroma correctly.)

To perform it in pixel shader, you'd have to convert it back to YUV exactly how it was converted to RGB, then convert it back to RGB correctly. The pixel shader never sees the YUV data, because it's already done by the time you can run a shader. Given the many possible ways to convert to RGB in the renderer, that's a pretty tall order, and madshi would have to help. Presumably, that workflow would also break dithering.

You have to do it in the decoding pipeline, not the rendering. Consider enabling ffdshow's avisynth processing and using that script to process the YUV data while decoding.

DarkSpace
28th March 2014, 13:00
To perform it in pixel shader, you'd have to convert it back to YUV exactly how it was converted to RGB, then convert it back to RGB correctly.
Why? From my limited understanding, shouldn't it be enough to separate Luma from Chroma using any matrix, then shift the Chroma channels (I think by 0.25 to the left?), and then convert back to RGB using the same matrix?

leeperry
28th March 2014, 17:58
OK thanks for the replies. I also thought that it would be fairly easy just like Darkspace is explaining it, I even assumed that YUY2 out of ffdshow would look properly aligned duh....I'll have to find a proper test pattern and give it a whirl.

leeperry
28th March 2014, 18:01
I'll just ask DragonQ for this sample (http://forum.doom9.org/showpost.php?p=1622754&postcount=18186) :)

JanWillem32
29th March 2014, 01:50
I have been thinking. Converting R'G'B' back to Y'CbCr is possible, but it will be in the 4:4:4 form. Given the context of video playback in this case, it is absolutely impossible to get the 4:2:2 or 4:2:0 chroma back as it was output by the decoder if any attempt of chroma-upsampling was made, with the notable exception of nearest neighbor filtering. Nearest neighbor filtering doesn't change any values nor discards any pixels. Given the 2:1 magnification factor, the sampling grid is simple as well. I already made pixel-shaded filters that exploit this trick. Both EVR and VMR-9 will use nearest neighbor chroma upsampling in certain cases (but still convert to flawed R'G'B' anyway). Fixing the internal stages of EVR or VMR-9 isn't possible. Using the renderer to convert the flawed R'G'B' back to 4:2:2 or 4:2:0 Y'CbCr, upsampling the chroma to 4:4:4 with one of the 15 filters I wrote and converting to R'G'B' again isn't ideal, but it does work. I'm fine with publicating the 15 chroma up-sampling up-sampling filters (in both common cositing modes) if people really want to use them. If anyone would like to have a sneak peak, you can open the file containg the source code for the internal filters I've written. It's the set of initial pass shaders in the bottom half of \src\filters\renderer\VideoRenderers\InternalDX9Shaders.h . However, the preferred fix for the problem is still of course to edit the renderer. As I said before, if you have access to the Y'CbCr mixing stages, implementing chroma upsampling for both common modes of cosited chroma is easy.

leeperry (first part), I advise to not give much regards to Leak's shader. None of the filtering stages do anything correctly. That shader should never be used.
As for the set of Avisynth filters, I can port a few on request. I guess that some of them could be useful.

foxyshadis, both madVR and my renderer in quality mode keep quantization high enough to generally not cause additional quantization artifacts than present in the source video. To be more specific; operations are done in single-precision floating point precision and intermediate storage of pixels in textures are formatted in half precision floating-point (lowest quality), 16-bit unsigned integer (very decent quality) or single-precision floating point (same as the processing format, mostly useful for debugging because of the high memory consumption). Between filtering stages pixels are never dithered. Dithering is only done in the very last filtering stage, as the backbuffer presented on the video adapter's output is merely 10-bit R'G'B' or worse, 8-bit R'G'B'. Breaking dithering stages is an artificial problem of all those old methods that employ poor quantization and vapid integer color processing methods of a bygone era.
In short, the video renderer stages don't have to bother with dithering at all until creating the output image for the video port.
On top of that, I'm really not a fan of moving any filters that the renderer should handle to some intermediate filtering pass attached to the decoder. Taking raw output from the decoder to the renderer is the best situation, partially because of the reasons I already noted. Sadly I'm stuck at the moment with the VMR-9, EVR, RealMedia an Quicktime mixers that are extremely limited in terms of input formats and various other capabilities. The renderer actually far exceeds the capabilities of the mixers. For madVR there are no such limitations, but that comes at the cost of the minimum processing efficiency of the mixer stages.

leeperry (second part), YUY2 (8-bit 4:2:2 Y'CbCr) has the same chroma cositing issues as any other 4:2:0 or 4:2:2 format.
As for the sample posted by DragonQ, I support the comment posted by nevcairiel following that sample. For what I've seen, the EVR and VMR-9 always upsample chroma using the MPEG1 method. (I actually don't understand why the MPEG2 chroma cositing method was ever implemented at all, as there are only disadvantages to it. Not that I really mind though, the cositing issues are just yet another fine example of what an absolutely terrible format Y'CbCr is and that it shoud be supplanted by a good implementation of color representation as soon as possible.)

yok833
30th March 2014, 07:06
Is it normal that when I apply lumasharpen several times in post or pre resize, there is no difference as if I had made it only once? I really would like to try this shader but I do not see any real difference (unlike of when I am using complex 2 or finesharp) so I am not sure to use it well...
However everything seems to be well configured (V 1.4.1) and I have also tried to rise the sharpening in the lumasharpen.hlsl file....
Maybe the sharpening is more light or subtle with this shader?

turbojet
30th March 2014, 07:25
It's not normal but there is at least one lumasharpen 1.4.1 out there that does nothing but load the gpu. Depending on settings it might not be very strong. If you open the file in a text editor what's next to strength and pattern?

http://forum.doom9.org/showthread.php?t=170357 (http://forum.doom9.org/showthread.php?t=170357) is the thread for lumasharpen, better to post your reply there.

CiNcH
28th June 2014, 09:42
Hi JanWillem32,

I am currently playing around with shaders and stuff. I am not a lot into D3D and video algorithms yet. There is one thing I wonder though. The vertices you define for resize shaders contain the texture coordinates in screenspace (so in pixels) rather than [0,1]. I wonder what difference that makes. I can't find anywhere that this is actually legal. I though D3D would clamp that to [0,1]. What happens with those texture coordinates? Are they passed to the shader?

JanWillem32
4th July 2014, 17:23
Texture coordinates are simply scaled in the space that you declare with the vertex declaration. For the resizers I just optimized the input and output parameters to suit the routines.
The vertices for the five main stages are set up like this:struct CUSTOMVERTEX_TEX1 {
float x, y, z, rhw, u, v;
};
...
// dCenterXo and dCenterYo already have .5 subtracted from them
float utlX = static_cast<float>(dTopLeftX + dCenterXo), utlY = static_cast<float>(dTopLeftY + dCenterYo);// offset to the top-left point
float utrX = static_cast<float>(dTopRightX + dCenterXo), utrY = static_cast<float>(dTopRightY + dCenterYo);// offset to the top-right point
float ublX = static_cast<float>(dBottomLeftX + dCenterXo), ublY = static_cast<float>(dBottomLeftY + dCenterYo);// offset to the bottom-left point
float ubrX = static_cast<float>(dBottomRightX + dCenterXo), ubrY = static_cast<float>(dBottomRightY + dCenterYo);// offset to the bottom-right point
float vidw = m_fVideoWidth - .5f, vidh = m_fVideoHeight - .5f, wndw = m_fWindowWidth - .5f, wndh = m_fWindowHeight - .5f;

__declspec(align(16)) CUSTOMVERTEX_TEX1 v[20] = {// lists for DrawIndexedPrimitive() with the number used for the BaseVertexIndex item
{-.5f, -.5f, 0.f, 1.f, 0.f, 0.f},// window size: 0
{wndw, -.5f, 0.f, 1.f, 1.f, 0.f},
{-.5f, wndh, 0.f, 1.f, 0.f, 1.f},
{wndw, wndh, 0.f, 1.f, 1.f, 1.f},
{-.5f, -.5f, 0.f, 1.f, 0.f, 0.f},// video size: 4
{vidw, -.5f, 0.f, 1.f, 1.f, 0.f},
{-.5f, vidh, 0.f, 1.f, 0.f, 1.f},
{vidw, vidh, 0.f, 1.f, 1.f, 1.f},
{utlX, utlY, 0.f, 1.f, -.5f, -.5f},// 1 pass resizers: 8
{utrX, utrY, 0.f, 1.f, vidw, -.5f},
{ublX, ublY, 0.f, 1.f, -.5f, vidh},
{ubrX, ubrY, 0.f, 1.f, vidw, vidh},
{utlX, -.5f, 0.f, 1.f, -.5f, 0.f},// 2 pass resizers x: 12
{utrX, -.5f, 0.f, 1.f, vidw, 0.f},
{ublX, vidh, 0.f, 1.f, -.5f, 1.f},
{ubrX, vidh, 0.f, 1.f, vidw, 1.f},
{-.5f, utlY, 0.f, 1.f, 0.f, -.5f},// 2 pass resizers y: 16
{wndw, utrY, 0.f, 1.f, 1.f, -.5f},
{-.5f, ublY, 0.f, 1.f, 0.f, vidh},
{wndw, ubrY, 0.f, 1.f, 1.f, vidh}
};

ryrynz
2nd September 2014, 09:00
Anyone else seen Samsung's auto depth enhancer at work on the U9000? It's IMO very effective, It brings about an almost 3D experience that I would hope other manufacturers apply to their TVs in future. With some excellent sharpeners already available how much work is it release something similar?

burfadel
2nd September 2014, 09:07
Anyone else seen Samsung's auto depth enhancer at work on the U9000? It's IMO very effective, It brings about an almost 3D experience that I would hope other manufacturers apply to their TVs in future. With some excellent sharpeners already available how much work is it release something similar?

That can be done, it's just a question of knowing how to do it and to do it so the performance penalty is low.

sucht
28th January 2015, 20:56
hi, is it possible to take an Avisynth script like FastLineDarken/FastLineDarkenMod and make a Pixel Shader out of it?

I want to post-process my anime DVD's in realtime without ffdshow/avisynth, because ffdshow and avisynth are crashing a lot.

We can use Video pixel shaders in somthing like MPC-HC, so i thought i ask here in this thread.... sorry if it was the wrong thing to do.



ciao
thomas

JanWillem32
28th January 2015, 21:14
There are some effects that are hard to implement in purely a pixel shader. For example the rotation shader mentioned earlier in the thread can't change the output vertices to produce a 1080×1920 image from a 1920×1080 image. These filters require renderer support (which can also be arranged, by the way). Effects that don't change the size of the output image nor require special intermediate steps in between pixel shaders (such as resizers and 3D shadow effects) can be implemented as simple pixel shaders.

sucht
29th January 2015, 00:08
Ok, so basically i'm better off using ffdshow and Avisynth for this Specific Stuff, because it sounds like alot of work and time is needed to make something like this, or better yet write a shader that does something similar.


Sorry for my English, and Thank you for your Time.



ciao
thomas

JanWillem32
29th January 2015, 00:40
I think you misunderstood. All effects can be achieved by pixel shaders and in some cases custom renderer steps for when you need control over textures, texture size, orientation and such. For the example of FastLineDarken/FastLineDarkenMod; these are mere sharpeners. I've written plenty of those already. I personally don't like sharpening very much (I dislike visual artifacts of any kind that deviate from good studio quality masters), but they are reasonably easy to write.

Shiandow
29th January 2015, 00:56
Ok, so basically i'm better off using ffdshow and Avisynth for this Specific Stuff, because it sounds like alot of work and time is needed to make something like this, or better yet write a shader that does something similar.

Sorry for my English, and Thank you for your Time.

ciao
thomas

I had a quick look, it doesn't seem too difficult to make something like FastLineDarken, although it would be quite a bit easier if you set it's "thinning" argument to 0. But I do agree that it would be a lot easier to make a shader that does something similar. If you just want to darken some lines you could take some simple sharpening shader like LumaSharpen and make a small change such that it only applies sharpening when the result is darker.

sucht
29th January 2015, 01:22
I did misunderstood you then, and i'm sorry.

I also don't like them much... but they(FastLineDarken/FastLineDarkenMod) helped some of my older Anime DVD's to look better when played with mpc-hc/madVR on my 50" 1080p TV.

I'm learning to write shaders(mostly for emulators), and that was more or less the reason of asking.

Nevertheless, i will use ffdshow and Avisynth and will try your Shaders, maybe i find something that i like, and can move on/away from ffdshow and avisynth.


and again Thank you for your Time.



ciao
thomas

XRyche
1st February 2015, 02:14
JanWillem32, your "(JW) H&V sharpen complex, deband, denoise SD-HD 16 bit FP for XLRCAM and LMS" that you created a while always have to be used with the "initial colour mixing stage" disabled. Is there any way to modify them to work without disabling colour mixing?

JanWillem32
1st February 2015, 02:56
No, there isn't. Though I would like a more extended shader control panel with a lot more shader stages as options, e.g.: 4:2:0-, 4:2:2 and 4:4:4-Y'CbCr stages, and a post-subtitle-OSD-stats-stage. Even with those, I would certainly allow users to disable the default initial passes to be able to use custom versions.

XRyche
1st February 2015, 03:37
No, there isn't. Though I would like a more extended shader control panel with a lot more shader stages as options, e.g.: 4:2:0-, 4:2:2 and 4:4:4-Y'CbCr stages, and a post-subtitle-OSD-stats-stage. Even with those, I would certainly allow users to disable the default initial passes to be able to use custom versions.

I didn't think so. Just wanted to check. I sometimes forget to disable colour mixing before I use those shaders and it makes me scratch my head for a moment :) .

burfadel
12th May 2015, 11:45
JanWillem32, I have a question relating to the 'semi-random grayscale noise' shader, part of the video pixel shader pack. I'm using the latest MPDN from Doom9 (http://forum.doom9.org/showthread.php?t=171120), set up for quality. There is an option in the settings to use shaders through the image processor. The shaders on options are available through the extensions pack, which you extract. The files then end up being in Extensions\RenderScripts\ImageProcessingShaders

Anyways, if I put your shader file in the MP-HC shader folder and enable it in MPDN, it doesn't work. If I alter the noise setting it still does nothing, unless I set a very extreme setting like 40/64 and the screen is white. Anything up to when it goes white, the picture is unchanged. This filter is of course, set last in the chain.

I was wondering whether you could take a look at this, as the shader is very good at perceptually increasing the picture quality. The added grain is very nice when set at a low, but visible strength being very small grains and only on the luma channel.

JanWillem32
12th May 2015, 14:35
That shader uses the time and frame counters. Try the "flash every frame" and "flash every second" from the development folder. If these don't work, the renderer isn't passing them and you should request the MPDN team for implementing these features.

Shiandow
12th May 2015, 15:09
They are implemented (sort of) although they might need some work. The problem seems to be that the value of c0.w is simply too large, at the moment it's the amount of time elapsed since 00:00, 01/01/0001, in tenths of microseconds.

What kind of values do your shaders expect?

JanWillem32
12th May 2015, 18:34
-c0.x shader stage width in pixels
-c0.y shader stage height in pixels
-c0.z source video frame count from start of playback
-c0.w source video time stamp in seconds from start of playback
-c1.x reciprocal of the shader stage width in pixels
-c1.y reciprocal of the shader stage height in pixels
-c1.z (post-resize) left whole pixel offset from the video rectangle to the display device
-c1.w (post-resize) top whole pixel offset from the video rectangle to the display device
-c2.x (post-resize) left normalized [0, 1] position of the borders of the video rectangle relative to the rendering stage window rectangle
-c2.y (post-resize) top normalized [0, 1] position of the borders of the video rectangle relative to the rendering stage window rectangle
-c2.z (post-resize) right normalized [0, 1] position of the borders of the video rectangle relative to the rendering stage window rectangle
-c2.w (post-resize) bottom normalized [0, 1] position of the borders of the video rectangle relative to the rendering stage window rectangle

c0.zw are 0-based, so intro-effects can work. They are also reset once in a while to deal with 16- and 32-bit floating-point limitations when counting.

Shiandow
12th May 2015, 19:33
Ok, thanks, I'll add a quick fix for the clock parameters.

burfadel
12th May 2015, 20:12
Ok, thanks, I'll add a quick fix for the clock parameters.

I'll let you know if that has fixed the issue for me :). It's a great shader when the grain is very slight, it brings 'life' to the picture.

James Freeman
23rd May 2015, 06:46
Hi Jan.

Is there a trapezoid correction for projectors somewhere inside your filter package?

JanWillem32
25th May 2015, 17:28
There are two shaders (which I should update with newer interpolation methods some time):
"development\3LCD panel horizontal software alignment, Catmull-Rom spline6 interpolated.txt" and
"development\3LCD panel vertical software alignment, Catmull-Rom spline6 interpolated.txt".
If you need a simpler or different effect I can write a custom one.

James Freeman
27th May 2015, 15:15
Thank you.
I have found the 3lcd shader and tried to use it, but with no success.
I could not create a trapezoid shape.

Maybe someting simpler that allows to control the geometry by pixel number XY in each corner,
Like 3LCD but all colors togethes.

JanWillem32
29th May 2015, 14:27
That's easy:// (C) 2015 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// projector panel horizontal software alignment, Catmull-Rom spline4 interpolated
// This shader should be run as a screen space pixel shader.
// This shader requires compiling with ps_2_0, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// This shader is meant to work with linear RGB input and output. Regular R'G'B' with a video gamma encoding will have to be converted with the linear gamma shaders to work properly.
// This shader can only work when the display device receives input in its native display resolution, with over- and underscan disabled. This is to facilitate 1:1 pixel mapping.
// This shader can perform software alignment by Catmull-Rom spline4 interpolation for a projector's panels.

// fractions, either decimal or not, are allowed
// set the horizontal resolution
#define HorizontalResolution 1920.
// ShiftLeftToRight, a value of 3. will shift three pixels to the right, 0 is disabled
#define ShiftLeftToRight 64.
// ScaleHorizontal, the centered horizontal magnification factor, a value of HorizontalResolution-3. will scale the output to 3 pixels larger, a value of HorizontalResolution means disabled
#define ScaleHorizontal HorizontalResolution-128.
// Parallelogram, the centered horizontal offset factor on the bottom, a value of 3. will shift 0 pixels to the left on the top, and 3 pixels to the left on the bottom, 0 is disabled
#define Parallelogram 256.
// Keystone, the centered horizontal magnification factor on the bottom, a value of -3. will scale the output to 0 pixels larger on the top, and 3 pixels larger on the bottom, 0 is disabled
#define Keystone -192.

sampler s0;
#define sp(A, O) float4 A = tex2D(s0, float2(coord+O/HorizontalResolution, tex.y));

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float coord = (tex.x-.5)*(ScaleHorizontal+tex.y*Keystone)+.5*HorizontalResolution-ShiftLeftToRight+tex.y*Parallelogram;// assign the output position, normalized to texture width in pixels
float t = frac(coord);// calculate the difference between the output pixel and the original surrounding two pixels
coord = (coord-t+.5)/HorizontalResolution;

sp(Q0, -1.) sp(Q1, 0.) sp(Q2, 1.) sp(Q3, 2.)// original pixels
// calculate weights
float4 w0123 = ((float4(-.5, 1.5, -1.5, .5)*t+float4(1., -2.5, 2., -.5))*t+float4(-.5, 0., .5, 0.))*t;
w0123.y += 1.;
return w0123.x*Q0+w0123.y*Q1+w0123.z*Q2+w0123.w*Q3;// interpolation output
}

James Freeman
29th May 2015, 16:40
Thank you.

Though, it does not work for me.
I can't create a trapezoid shape at all.

Maybe I should be more specific?
My goal is narrow the upper or lower part of the image to create a symmetric trapezoid.
http://etc.usf.edu/clipart/40600/40699/pb_trp_40699_lg.gif

The current shader also stretches the sides when changing shape, while the correct way is to make everything black outside the image.

JanWillem32
29th May 2015, 19:52
Same shader, but with added borders:// (C) 2015 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// projector panel horizontal software alignment, Catmull-Rom spline4 interpolated with borders
// This shader should be run as a screen space pixel shader.
// This shader requires compiling with ps_2_0, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// This shader is meant to work with linear RGB input and output. Regular R'G'B' with a video gamma encoding will have to be converted with the linear gamma shaders to work properly.
// This shader can only work when the display device receives input in its native display resolution, with over- and underscan disabled. This is to facilitate 1:1 pixel mapping.
// This shader can perform software alignment by Catmull-Rom spline4 interpolation for a projector's panels and apply borders where the signal is cut off.

// fractions, either decimal or not, are allowed
// set the horizontal resolution
#define HorizontalResolution 1920.
// ShiftLeftToRight, a value of 3. will shift three pixels to the right, 0 is disabled
#define ShiftLeftToRight 64.
// ScaleHorizontal, the centered horizontal magnification factor, a value of HorizontalResolution-3. will scale the output to 3 pixels larger, a value of HorizontalResolution means disabled
#define ScaleHorizontal HorizontalResolution-128.
// Parallelogram, the centered horizontal offset factor on the bottom, a value of 3. will shift 0 pixels to the left on the top, and 3 pixels to the left on the bottom, 0 is disabled
#define Parallelogram 256.
// Keystone, the centered horizontal magnification factor on the bottom, a value of -3. will scale the output to 0 pixels larger on the top, and 3 pixels larger on the bottom, 0 is disabled
#define Keystone -192.
// BorderColor, the color to apply at the borders created by this shader
#define BorderColor float4(0., 0., 0., 1.)

sampler s0;
#define sp(A, O) float4 A = BorderColor; {float pl = coord+O/HorizontalResolution; if(all(float2(pl, -pl) >= float2(0., -1.))) A = tex2D(s0, float2(pl, tex.y));}

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float coord = (tex.x-.5)*(ScaleHorizontal+tex.y*Keystone)+.5*HorizontalResolution-ShiftLeftToRight+tex.y*Parallelogram;// assign the output position, normalized to texture width in pixels
float t = frac(coord);// calculate the difference between the output pixel and the original surrounding two pixels
coord = (coord-t+.5)/HorizontalResolution;

sp(Q0, -1.) sp(Q1, 0.) sp(Q2, 1.) sp(Q3, 2.)// original pixels
// calculate weights
float4 w0123 = ((float4(-.5, 1.5, -1.5, .5)*t+float4(1., -2.5, 2., -.5))*t+float4(-.5, 0., .5, 0.))*t;
w0123.y += 1.;
return w0123.x*Q0+w0123.y*Q1+w0123.z*Q2+w0123.w*Q3;// interpolation output
}

James Freeman
30th May 2015, 09:14
Jan sorry to bother you, but this shader simply can't create a trapezoid shape I posted above.

JanWillem32
30th May 2015, 15:51
Really?
I get a nice bordered (red) keystone with these values:

// fractions, either decimal or not, are allowed
// set the horizontal resolution
#define HorizontalResolution 1920.
// ShiftLeftToRight, a value of 3. will shift three pixels to the right, 0 is disabled
#define ShiftLeftToRight 0.
// ScaleHorizontal, the centered horizontal magnification factor, a value of HorizontalResolution-3. will scale the output to 3 pixels larger, a value of HorizontalResolution means disabled
#define ScaleHorizontal HorizontalResolution-
// Parallelogram, the centered horizontal offset factor on the bottom, a value of 3. will shift 0 pixels to the left on the top, and 3 pixels to the left on the bottom, 0 is disabled
#define Parallelogram 0.
// Keystone, the centered horizontal magnification factor on the bottom, a value of -3. will scale the output to 0 pixels larger on the top, and 3 pixels larger on the bottom, 0 is disabled
#define Keystone -777.
// BorderColor, the color to apply at the borders created by this shader
#define BorderColor float4(1., 0., 0., 1.)

Notice "HorizontalResolution-" for ScaleHorizontal, it's a trick for auto-aligning negative keystone values.

James Freeman
30th May 2015, 18:19
Now try to create the shape I posted with the narrow side on top.
The border also don't touch the end of the screen.

JanWillem32
30th May 2015, 18:41
The keystone the other way around is easy. Is this what you want?

// fractions, either decimal or not, are allowed
// set the horizontal resolution
#define HorizontalResolution 1920.
// ShiftLeftToRight, a value of 3. will shift three pixels to the right, 0 is disabled
#define ShiftLeftToRight 0.
// ScaleHorizontal, the centered horizontal magnification factor, a value of HorizontalResolution-3. will scale the output to 3 pixels larger, a value of HorizontalResolution means disabled
#define ScaleHorizontal HorizontalResolution+777.
// Parallelogram, the centered horizontal offset factor on the bottom, a value of 3. will shift 0 pixels to the left on the top, and 3 pixels to the left on the bottom, 0 is disabled
#define Parallelogram 0.
// Keystone, the centered horizontal magnification factor on the bottom, a value of -3. will scale the output to 0 pixels larger on the top, and 3 pixels larger on the bottom, 0 is disabled
#define Keystone -777.
// BorderColor, the color to apply at the borders created by this shader
#define BorderColor float4(1., 0., 0., 1.)

James Freeman
30th May 2015, 18:51
Thank you.

Magik Mark
30th May 2015, 23:06
Sorry for my ignorance, how do we apply this in MPDN player? It uses hsl extension.

foxyshadis
30th May 2015, 23:36
Sorry for my ignorance, how do we apply this in MPDN player? It uses hsl extension.

The extension doesn't matter, although it defaults the same as MPC, .hlsl. You want to select Image Processor (by itself or in a script chain), open its properties, click '+', and find the shader you want. You'll have to configure everything within the shader in notepad or similar, since there's no internal shader editor.

James Freeman
4th June 2015, 10:20
Can anyone please suggest a shader for white balance correction R,G,B?
I tried some of the shaders in the pixel shader pack but it also changes the contrast, brightness or gamma on each color.

Is there a shader that changes just the R,G,B Levels (not contrast, brightness, or gamma), for white balance fixing.
This is for my not so good projector in which the color management is non existent.

Thank you.

JanWillem32
4th June 2015, 22:22
There's the Multi-stage gamma controls (http://forum.doom9.org/showthread.php?p=1650254#post1650254) shader you asked for before. For altering the high red, green and blue values I could alter the z-segment to not end on 1 (full intensity) or add contrast and brightness controls there.
What controls do you need exactly? (Note that altering this particular shader with more advanced features will take some time and effort. It's rather complicated.)

James Freeman
7th June 2015, 10:33
Hi Jan.

I need a shader that alters the RGB levels just like a TV or a Monitor.
NOT contrast, brightness or gamma; just R,G,B LEVELS (in floating point of course).
It should effect luma and chroma, just like tweaking the display pixels themselves.

Just remove or add Green (for example) across the whole range, without effecting the contrast or brightness.

Thanks

JanWillem32
7th June 2015, 17:21
I don't have a clue what to implement for a "levels" control to be honest.

The RGB controls act on a linear 0 to 1 function.
-Changing the origin of the linear 0 to 1 function changes brightness (and dislodges the black and white points from their origins in the process).
-Changing the angle of the linear 0 to 1 function changes contrast (and dislodges the white point from its origin in the process).
-Applying a power function to the linear 0 to 1 function changes gamma (and keeps the black and white points on their origins in the process).
(None of the controls are really independent.)

Higher complexity than that can involve applying S-curves to the function, but these behave similar to gamma controls.
The the Multi-stage gamma controls shader also adds higher complexity in the form of allowing the user to set way-points for the gamma controls.

Beyond these functions I don't have a clue what function to add, especially one that doesn't "alter" contrast, brightness or gamma.

James Freeman
7th June 2015, 18:20
I don't have a clue what to implement for a "levels" control to be honest.
The RGB controls act on a linear 0 to 1 function.
-Changing the origin of the linear 0 to 1 function changes brightness (and dislodges the black and white points from their origins in the process).
-Changing the angle of the linear 0 to 1 function changes contrast (and dislodges the white point from its origin in the process).
-Applying a power function to the linear 0 to 1 function changes gamma (and keeps the black and white points on their origins in the process).
(None of the controls are really independent.)


Thank you!

Apparently it is a simple Brightness control for R,G,B which dislodges the black and white linearly.
I even think that something like this already exists.

EDIT:
I does exist!
called: brightness, contrast and gamma controls for RGB
Sorry to bother you once again Jan.

nevcairiel
7th June 2015, 18:57
Most graphics drivers have such settings as well, which might be easier and more universally useful.

romulous
21st October 2015, 13:50
Hi JanWillem,

Any chance of an updated pack with all the new scripts, and changes you have made to the existing scripts over the years (the current pack is dated 2011)?

romulous

JanWillem32
21st October 2015, 18:17
I could use some help with collecting all the newer pixel shaders and putting them into .txt files. I don't have all of them on file anymore. After that, it's going to take a while for me to re-vamp all the shaders. Some use pretty outdated methods, all of them need renewed main comments and some could use some comments in the programming details.

vBm
21st October 2015, 23:56
I could use some help with collecting all the newer pixel shaders and putting them into .txt files. I don't have all of them on file anymore. After that, it's going to take a while for me to re-vamp all the shaders. Some use pretty outdated methods, all of them need renewed main comments and some could use some comments in the programming details.

IMHO ideal would be to have repository for shaders on github or whenever xD

andybkma
3rd December 2015, 02:57
Hi, new to the whole shader thing as Zoom Player just achieved support for them. My question is if there is a shader that approximates the effects of using Avisynth script Limited Sharpen Faster (LSF) in real time? Would be nice to finally stop having to use LSF in order to drastically improve the pic quality of videos. Thanks

XRyche
4th December 2015, 00:33
Hi, new to the whole shader thing as Zoom Player just achieved support for them. My question is if there is a shader that approximates the effects of using Avisynth script Limited Sharpen Faster (LSF) in real time? Would be nice to finally stop having to use LSF in order to drastically improve the pic quality of videos. Thanks

JanWillem32 is away for a bit but to my knowledge he doesn't have any shaders like that. The best sharpening shader he has is a tweaked unsharpenmask shader intended for pre-processing.

I don't even think LSF can even be ported to HLSL? If it could I imagine it would have already been done.

There is "Adaptive sharpen" http://forum.doom9.org/showthread.php?t=172131 which can be a decent shader sharpener if used right.

IanD
19th October 2017, 00:43
I'm interested in using a shader to scale 1920x1080 video to 3840x2160 using a 2x2 matrix via a lookup table, operating on each pixel in the source frame in turn, not convolving 2x2 groups of pixels (ie similar to point resize but setting each pixel in the 2x2 block to a different value based on the matrix, not setting each pixel the same as the source pixel).

Can anyone point me in the right direction of tutorials to understand how to do this, or to explain why it can't be done this way?

My 4k LG OLED TV has quantisation issues near black where the effective bit depth is less than 8 bits (for an alleged 10 bit panel). I want to see whether a simple spatial 2x2 dither of 8 bit 1920x1080 inputs to 6 bit 3840x2160 output can help ameliorate the issue, with a further development of only applying the dither to near black pixels and using a more advanced scaling for non near black pixels. I wasn't interested in a traditional diffusion dither because I think LG already uses this and it creates an obviously much noisier image.

jeanlee20xx
18th December 2017, 07:41
I want play 2d as SBS,how to write the code?thank you!!!!:thanks::thanks::thanks::thanks:

PCU
15th February 2018, 14:34
request: deblocker shader for low quality videos like old bink videos.

JNW
20th February 2018, 05:44
I don’t think anyone ever made a deblocking shader. This is usually accomplished with postprocessing like in Potplayer. Why don’t you use ffdshow raw filter that way you can still use MPC-HC and LAV.

A good shader for MPC-HC I always thought would be Lumasharpen. Works just like in madVR https://gist.github.com/sthalik/c1b09db3465001e31144

PCU
20th February 2018, 16:17
well ffdshow is dead, isn't it?

JNW
20th February 2018, 17:26
Yes, that’s true but if you’re only using it for the deblocking feature it doesn’t really matter. Think of it as using a shader, they don’t get updated.

PCU
20th February 2018, 19:13
Yes, that’s true but if you’re only using it for the deblocking feature it doesn’t really matter. Think of it as using a shader, they don’t get updated.

how to deblock this file (max payne 2 intro) correctly?
http://www.filepup.net/files/a0ba90621519150241.html
no, maybe shaders gets updated, but ffdshow (even tryouts) is 100% dead & ffdshow has lots of other features that i don't use.

v0lt
22nd February 2018, 20:41
well ffdshow is dead, isn't it?
No, ffdshow also works well as before.
no, maybe shaders gets updated, but ffdshow (even tryouts) is 100% dead & ffdshow has lots of other features that i don't use.
The presence of additional functionality does not prevent to use only what is needed.

JNW
23rd February 2018, 09:18
Thanks v0lt what I was getting at.

I've uploaded a couple of shaders. These are from the SweetFX shader pack which I had laying around from many moons ago where some were updated for better use in MPC. I'm uploading them for people running old or low spec PC (I still have one laying around myself) and are unable to use madVR to its full advantage. Simply put it in the shader folder.

The first one is LumaSharpen and better than the one I posted before as it has a default strength of 0.65 same as madVR so you don't have to go in and change it.
http://s000.tinyupload.com/index.php?file_id=00110955234181062890

The second is a sort of faux HDR shader to try and imitate it.
http://s000.tinyupload.com/index.php?file_id=09603921432233252135

As I said for low spec but maybe it will help somebody.

j82k
22nd April 2018, 00:01
Is it possible to modify a shader so that it is only applied to part of the picture? I found this LCD angle correction shader here: https://github.com/zachsaw/RenderScripts/blob/master/RenderScripts/ImageProcessingShaders/MPC-HC/LCD%20angle%20correction.hlsl

My intend is to reduce the vertical banding on my Oled TV and I think this shader could work if it can be modified to only apply to a user defined vertical column of the picture, for example from pixel 2880 to 3260. I have zero knowledge about shader writing and only got so far as to make the shader correction horizontal instead of vertical. Is what I want possible and can anyone do it??

v0lt
22nd April 2018, 06:43
JNW
Can I add the LumaSharpen shader to MPC-BE?

JNW
30th April 2018, 23:27
JNW
Can I add the LumaSharpen shader to MPC-BE?

Absolutely add it MPC-BE, I think that’s a great idea. It’s great for people using EVR-CP, it’s low on resources and as I pointed out it has a default strength of 0.65 and works exactly the same as in madVR. I find it can be as useful as YV12 Chroma Upsampling when using EVR-CP. LumsSharpen is a really good shader that is missing so by all means add it to MPC-BE that would be perfect. :)

v0lt
1st May 2018, 14:10
JNW
Thank you. The LumaSharpen shader is added to MPC-BE 1.5.2.3576.