mirror of
https://github.com/libretro/slang-shaders.git
synced 2024-11-23 08:19:54 +00:00
update crt-guest-dr-venom
This commit is contained in:
parent
b340d6cee3
commit
96c592851a
40
crt/crt-guest-dr-venom-fast.slangp
Normal file
40
crt/crt-guest-dr-venom-fast.slangp
Normal file
@ -0,0 +1,40 @@
|
||||
shaders = 5
|
||||
|
||||
shader0 = shaders/guest/lut/lut.slang
|
||||
filter_linear0 = false
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
||||
|
||||
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3"
|
||||
SamplerLUT1 = shaders/guest/lut/sony_trinitron1.png
|
||||
SamplerLUT1_linear = true
|
||||
SamplerLUT2 = shaders/guest/lut/sony_trinitron2.png
|
||||
SamplerLUT2_linear = true
|
||||
SamplerLUT3 = shaders/guest/lut/other1.png
|
||||
SamplerLUT3_linear = true
|
||||
|
||||
shader1 = shaders/guest/fast/smoothing.slang
|
||||
filter_linear1 = false
|
||||
scale_type1 = source
|
||||
scale1 = 1.0
|
||||
alias1 = SmoothPass
|
||||
|
||||
shader2 = shaders/guest/fast/linearize-multipass.slang
|
||||
filter_linear2 = false
|
||||
scale_type2 = source
|
||||
scale2 = 1.0
|
||||
float_framebuffer2 = true
|
||||
|
||||
shader3 = shaders/guest/fast/crt-guest-dr-venom-pass1.slang
|
||||
filter_linear3 = false
|
||||
scale_type_x3 = viewport
|
||||
scale_x3 = 1.0
|
||||
scale_type_y3 = source
|
||||
scale_y3 = 1.0
|
||||
float_framebuffer3 = true
|
||||
|
||||
shader4 = shaders/guest/fast/crt-guest-dr-venom-pass2.slang
|
||||
filter_linear4 = false
|
||||
scale_type4 = viewport
|
||||
scale_x4 = 1.0
|
||||
scale_y4 = 1.0
|
@ -1,43 +1,68 @@
|
||||
shaders = 7
|
||||
shaders = 10
|
||||
|
||||
shader0 = shaders/guest/afterglow.slang
|
||||
shader0 = shaders/guest/lut/lut.slang
|
||||
filter_linear0 = false
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
||||
|
||||
shader1 = shaders/guest/d65-d50.slang
|
||||
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3"
|
||||
SamplerLUT1 = shaders/guest/lut/sony_trinitron1.png
|
||||
SamplerLUT1_linear = true
|
||||
SamplerLUT2 = shaders/guest/lut/sony_trinitron2.png
|
||||
SamplerLUT2_linear = true
|
||||
SamplerLUT3 = shaders/guest/lut/other1.png
|
||||
SamplerLUT3_linear = true
|
||||
|
||||
shader1 = shaders/guest/color-profiles.slang
|
||||
filter_linear1 = false
|
||||
scale_type1 = source
|
||||
scale1 = 1.0
|
||||
alias1 = temp_pass
|
||||
|
||||
shader2 = shaders/guest/avg-lum.slang
|
||||
shader2 = shaders/guest/d65-d50.slang
|
||||
filter_linear2 = false
|
||||
scale_type2 = source
|
||||
scale2 = 1.0
|
||||
mipmap_input2 = true
|
||||
alias2 = lum_pass
|
||||
alias2 = WhitePointPass
|
||||
|
||||
shader3 = shaders/guest/linearize.slang
|
||||
shader3 = shaders/guest/afterglow.slang
|
||||
filter_linear3 = false
|
||||
scale_type3 = source
|
||||
scale3 = 1.0
|
||||
float_framebuffer3 = true
|
||||
alias3 = linearize_pass
|
||||
alias3 = AfterglowPass
|
||||
|
||||
shader4 = shaders/guest/blur_horiz.slang
|
||||
shader4 = shaders/guest/avg-lum0.slang
|
||||
filter_linear4 = false
|
||||
scale_type4 = source
|
||||
scale4 = 1.0
|
||||
float_framebuffer4 = true
|
||||
|
||||
shader5 = shaders/guest/blur_vert.slang
|
||||
shader5 = shaders/guest/avg-lum.slang
|
||||
filter_linear5 = false
|
||||
scale_type5 = source
|
||||
scale5 = 1.0
|
||||
float_framebuffer5 = true
|
||||
mipmap_input5 = true
|
||||
alias5 = AvgLumPass
|
||||
|
||||
shader6 = shaders/guest/crt-guest-dr-venom.slang
|
||||
filter_linear6 = true
|
||||
scale_type6 = viewport
|
||||
shader6 = shaders/guest/linearize.slang
|
||||
filter_linear6 = false
|
||||
scale_type6 = source
|
||||
scale6 = 1.0
|
||||
float_framebuffer6 = true
|
||||
alias6 = LinearizePass
|
||||
|
||||
shader7 = shaders/guest/blur_horiz.slang
|
||||
filter_linear7 = false
|
||||
scale_type7 = source
|
||||
scale7 = 1.0
|
||||
float_framebuffer7 = true
|
||||
|
||||
shader8 = shaders/guest/blur_vert.slang
|
||||
filter_linear8 = false
|
||||
scale_type8 = source
|
||||
scale8 = 1.0
|
||||
float_framebuffer8 = true
|
||||
|
||||
shader9 = shaders/guest/crt-guest-dr-venom.slang
|
||||
filter_linear9 = true
|
||||
scale_type9 = viewport
|
||||
scale_x9 = 1.0
|
||||
scale_y9 = 1.0
|
||||
|
365
crt/shaders/guest/README
Normal file
365
crt/shaders/guest/README
Normal file
@ -0,0 +1,365 @@
|
||||
____ ____ _____ ____ _ ____ __ __
|
||||
/ ___| _ \_ _| / ___|_ _ ___ ___| |_ | _ \ _ _\ \ / /__ _ __ ___ _ __ ___
|
||||
| | | |_) || |_____| | _| | | |/ _ \/ __| __|____| | | | '__\ \ / / _ \ '_ \ / _ \| '_ ` _ \
|
||||
| |___| _ < | |_____| |_| | |_| | __/\__ \ ||_____| |_| | |_ \ V / __/ | | | (_) | | | | | |
|
||||
\____|_| \_\|_| \____|\__,_|\___||___/\__| |____/|_(_) \_/ \___|_| |_|\___/|_| |_| |_|
|
||||
|
||||
CRT - Guest - Dr.Venom
|
||||
|
||||
Copyright (C) 2018-2019 guest(r) - guest.r@gmail.com
|
||||
|
||||
Incorporates many good ideas and suggestions from Dr.Venom.
|
||||
|
||||
|
||||
This guide: Rev 1, April 28th 2019
|
||||
|
||||
|
||||
----------------
|
||||
# Introduction #
|
||||
----------------
|
||||
|
||||
This shader mimics the look of Cathode Ray Tubes (CRTs) on modern LCD monitors.
|
||||
Its main goal is to be accurate out of the box, and keep plenty of customization options for the CRT purists to tinker with. That's you if you're reading this :)
|
||||
|
||||
Since the range of shader parameters can be a bit overwhelming we've created this little readme to explain some of the options.
|
||||
|
||||
If you have questions, please don't hesitate to reach out to us!
|
||||
|
||||
Most of the stuff in this guide has been discussed on English Amiga Board here: http://eab.abime.net/showthread.php?t=95969&page=2
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
# Afterglow #
|
||||
--------------
|
||||
|
||||
The RGB phosphors in CRTs have a decay time when going from fully lit to off. When going from bright lit status to off the luminance level instantly falls to about 10%, but then tend to linger at that level for a bit. This is what we call "afterglow". This afterglow of phosphors causes slightly visible trails when bright objects are moving fast on a dark background.
|
||||
|
||||
For an example of this "CRT phosphor afterglowing" see this video on youtube: https://youtu.be/N72uiXFgrh0
|
||||
|
||||
If you look at the UFO flying by from second 13 to 18 you can clearly see the trail in motion. In the video it looks slightly exaggerated because of the way cameras work.
|
||||
|
||||
The shader allows to control the strength of afterglow per Red, Green, Blue "phospors". Generally the blue phosphor has the least afterglow, so you may want to have red and green a bit stronger than blue.
|
||||
|
||||
Afterglow switch ON/OFF // Turn afterglow feature ON/OFF
|
||||
Afterglow Red (more is more) // controls the initial brightness of the afterglow on the red phosphor. Higher values makes red more visible in the afterglow. Default is 0.07
|
||||
Persistence Red (more is less) // Controls the decay time, i.e. if red should fade away quickly from its initial brightness or slowly. A higher value makes the red phosphor fade away more quickly. Default value is 0.05.
|
||||
Afterglow Green
|
||||
Persistence Green
|
||||
Afterglow Blue
|
||||
Persistence Blue
|
||||
Afterglow saturation // Determines the saturation of the RGB afterglow. Generally afterglow has very low saturation so it defaults to a low value of 0.1. Higher values give more saturation.
|
||||
|
||||
-------------
|
||||
# TATE mode #
|
||||
-------------
|
||||
|
||||
Yes we do in weird lingo :) In short TATE means "vertical" orientation for arcade monitors. The term ”Tate” is apparently a shortened form of the Japanese verb “tateru,” which means “to stand.” Pronounced “tah-teh,” though the common mispronunciation of “tayte” has gained semi-acceptance. Also commonly spelled with all capital letters (“TATE”), though it is not an acronym.
|
||||
|
||||
In the shader when you set TATE to 1 both the scanlines and mask orientation will rotate by 90 degrees to accommodate to Arcade games that are in vertical orientation, like 1942 shooters and the like. Mostly useful for when running MAME vertical games.
|
||||
|
||||
-------------------------
|
||||
# Smart Integer Scaling #
|
||||
-------------------------
|
||||
|
||||
When the video scaling is set to full screen, it may happen that the scanlines appear slightly uneven. To remedy this you can enable this option. It will scale vertically to the nearest suitable integer scale factor. The "smart" part is that it will take into account "overscan" as it appeared on TVs, so it may scale the image slightly larger than the screen size to keep things full screen while also enabling integer scale factor. When it makes use of this overscan up to about 10% of the image may fall outside of the visible area. If the nearest integer larger scale factor would go over this this bound, it chooses the nearest lower integer scale, which will come at the cost of some black bars around the image. Just try and learn :).
|
||||
|
||||
Values are:
|
||||
0 = off
|
||||
1 = smart integer scale vertically
|
||||
2 = smart integer scale vertically and keep aspect ratio
|
||||
|
||||
----------------
|
||||
# Raster Bloom #
|
||||
----------------
|
||||
|
||||
Raster bloom is a feature that occurs on some CRTs, where the image will slightly expand on brighter images. This may give some extra "pop" to short flashing bright images, like big explosions and such. Almost all CRTs are experiencing raster bloom to some extent, but how much and whether it's really visible depends largely on the CRT model and how much it has aged / been maintained.
|
||||
|
||||
The following two youtube videos show examples of raster blooming.
|
||||
|
||||
The first movie shows metal slug on a CRT TV. If you go to second 75 and look at the bottom right where it says "Credit 04", you'll see how this text gets pushed slightly to the outside of the bezel when the screen gets bright and it coming back in on darker screens. This is sort of the default case where bloom sizes up the image by 1 to 2%.
|
||||
|
||||
https://youtu.be/_K-kTSUaekk
|
||||
|
||||
The next one shows an older TV where the voltage regulation has clearly been diminished. From 1:15 in this youtube:
|
||||
|
||||
https://youtu.be/zbGYwPwf-zA
|
||||
|
||||
The guy is turning the brightness of the monitor up and down. You can see how the white raster expands quite a bit when the brightness on the monitor is turned up and then shrinks back when it's lowered. This is what we call the 10% blooming case. I.e. it has a defect and needs servicing, opposed to the 1 - 2% normal bloom on properly calibrated sets.
|
||||
|
||||
The following parameters control Raster Bloom in the shader:
|
||||
|
||||
Raster bloom % // This determines the raster bloom scale factor. A value of 2 to 3% will result in realistic raster bloom. Larger values will exaggerate the effect, or you're really into mimicking a faulty CRT :).
|
||||
R. Bloom Overscan Mode // This setting determines whether a fully bright image may push the image outside of the screen / bezel or not. Possible settings:
|
||||
|
||||
(This assumes that automatic full screen scaling is enabled in Retroarch video options.)
|
||||
0 = Raster bloom is always within the boundaries of the visible screen
|
||||
1 = holds the middle between option 0 and 2 :)
|
||||
2 = Raster bloom pushes part of the image outside of the visible area on bright screens.
|
||||
|
||||
Setting 1 and 2 more or less mimic the behavior as seen in the metal slug x video mentioned above.
|
||||
|
||||
-------------------------
|
||||
# Saturation adjustment #
|
||||
-------------------------
|
||||
|
||||
This controls how saturated the image is. Higher values give more saturation. This may be useful with emulated systems like e.g. SNES, which tend to have a more saturated image than default.
|
||||
|
||||
--------------------------
|
||||
# Gamma In and Gamma Out #
|
||||
--------------------------
|
||||
|
||||
Setting Gamma In ("input gamma") to 2.4 affects the following:
|
||||
|
||||
- horizontal interpolation is done in gamma space, where brighter colors spread a bit more over darker ones. Should match interpolation of CRT's.
|
||||
- scanlines are applied differently
|
||||
- masks are better distributed over the spectrum
|
||||
|
||||
Generally it's best to keep this value at the default of 2.4 as it mostly concerns a shader internal conversion step where this default value results in desired behavior
|
||||
|
||||
|
||||
Gamma Out:
|
||||
|
||||
Of course we have to switch back to the normal color space, so there is the Gamma Out out functionality. In some CRT shaders it's about 10% lower compared with the input gamma. Different input/output gamma values affect saturation and brightness.
|
||||
|
||||
Since there is an option to use neutral input/output gamma (1.0), you can observe the difference within the shader.
|
||||
|
||||
I think most importantly is that this part of the shader functions as intended and can be tweaked to personal preference.
|
||||
|
||||
I think the most catchy part here is that CRT's have this 2.2-2.25 gamma and I defaulted 2.4. It roots in sRGB a bit and I got used to it. You can set output gamma (often referred to as CRT gamma) to 2.25 np.
|
||||
|
||||
From the CRT color research (at the end of this section) it was found that the researched CRTs had a Gamma of 2.25. So to have the shader color profiles displayed properly one has to set the Gamma Out to 2.25.
|
||||
|
||||
|
||||
----------------
|
||||
# Bright boost #
|
||||
----------------
|
||||
|
||||
This setting makes the image brighter. Making the image brighter is useful / necessary when scanlines are enabled, as scanline simulation reduces brightness of the image.
|
||||
|
||||
Good values for "bright boost" are between 1.1 and 1.3 depending on preference. Note that there's a tradeoff, higher values for brightboost make the image brighter, but can cause clipping of colors, making the image become more "flat". On lower color systems, like 8-bit, this clipping may be seen as soon as you go over 1.2. It's best to experiment a bit to see what suits one's own taste.
|
||||
|
||||
-------------
|
||||
# Scanlines #
|
||||
-------------
|
||||
|
||||
One of the most distinguishable features of CRTs when run in progressive mode are visible scanlines. I.e. the image is characterized by distinguishable brighter lines (the "scanlines"), and darker/black in-between lines. Sometime people refer to these darker lines when they say scanlines, but the bottom line is the same ;-)
|
||||
|
||||
Since good scanline simulation is one of the most determining aspects of good CRT simulation, there are no less than 5 parameters that control this feature:
|
||||
|
||||
Scanline Type // 0 = normal scanlines; 1 = more intense scanline type ; 2 = more aggressive / accentuated scanline type. Default = 0
|
||||
Scanline beamshape // The scanline beamshape "low" and "high" parameters define the look of the scanlines. With these two settings the scanlines can be made thinner or thicker, less or more rounded at the edges and degrees between them. In particular the scanline beamshape low value defines the scanline shape near the middle and the beamshape high value defines the scanline shape near the edges. For example a setting of 5.0,15.0 creates a stronger but more flat like looking scanline. The default values work very well, but you may want to experiment depending on your screen resolution and preference.
|
||||
Scanline dark // On a real CRT darker scanlines are thinner than bright scanlines. This setting determines by how much. Raising the value makes them thinner. Default is 1.35.
|
||||
Scanline bright // On a real CRT bright scanlines are thicker than darker scanlines. This setting determines how much thicker. Lowering the values will make them thicker. Default is 1.10.
|
||||
Increased bright scanline beam // This accentuates the brighter parts or pixels within a single scanline. On a real CRT bright pixels within a scanline will appear thicker. This setting controls by how much. Default is 0.65.
|
||||
|
||||
---------------------------
|
||||
# Sharpness and smoothing #
|
||||
---------------------------
|
||||
|
||||
The following parameters determine the smoothness versus sharpness balance of the image.
|
||||
|
||||
A real CRT has the peculiar but very nice characteristic that single pixels are smooth, while the overall image is sharp. This opposed to modern LCDs, where both individual pixels and the total image are very sharp. To recreate the soft "pillow shape" phosphor dot characteristics while keeping overall image sharp there 4 parameters that control this balance.
|
||||
|
||||
Horizontal sharpness // This setting determines the overall image sharpness mostly. Higher values create a sharper image. Default is 5.25.
|
||||
Substractive sharpness // This is a nice "hack" that may be used in combination with "horizontal sharpness". Higher values give more sharpness to pixels and mask. Default is 0.05.
|
||||
Horizontal Smoothing // This is some candy that blends pixels more that are close in color tint to each other. Gives a nice touch to especially high color systems that have many grades of color (like playstation).
|
||||
Smart Smoothing Threshold // This works in cooperation with "Horizontal Smoothing". It sets the threshold for how far apart "same" color tints must be for horizontal smoothing to apply.
|
||||
|
||||
-------------
|
||||
# Curvature #
|
||||
-------------
|
||||
|
||||
The physical properties of (earlier) shadow mask CRTs make them to have a slightly curved screen. For some of these CRTs the image may appear slightly curved as well, although that largely depends on make and model and how well the set is calibrated. The following two parameters allow for the curvature to be configured in the vertical and horizontal direction.
|
||||
|
||||
CurvatureX // default is OFF. In case you like curvature, a recommended value is 0.03.
|
||||
CurvatureY // Default is OFF. In case you like curvature, a recommended value is 0.04.
|
||||
|
||||
--------
|
||||
# Glow #
|
||||
--------
|
||||
|
||||
Phosphors typically create a small surrounding glow on objects. This is especially noticeable when bright objects are shown on a dark background, and even more so when watching a CRT in a dim environment. Whether this glow exists because the light emission gets scattered slightly in the front glass of the tube or something else we would like to know :).
|
||||
|
||||
In the shader the glow strength, radius and grade (fall-off) can be configured.
|
||||
|
||||
Glow Strength // Determines the overall strength of the glow . Default is 0.02.
|
||||
H. Glow Radius // Determines the radius of the glow in horizontal direction. Higher values create a bigger radius. Default is 4.0.
|
||||
Horizontal Glow Grade // Determines the grade/ fall-off / fade of the glow. Higher values make the glow fade out more quickly.
|
||||
V. Glow Radius // Same as horizontal parameter but for vertical.
|
||||
Vertical Glow Grade // Same as horizontal parameter but for vertical.
|
||||
|
||||
--------
|
||||
# Mask #
|
||||
--------
|
||||
|
||||
Together with scanlines the second most distinguishable feature of CRTs is the very subtle pattern, also called "mask", apparent in images displayed on a CRT. The type of pattern largely depends on the technology used, shadow mask (dotmask and slotmask) versus aperture grille (trinitron). All these types of masks can be simulated with the shader.
|
||||
|
||||
CRT Mask: 0:CGWG, 1-4:Lottes, 5-6:'Trinitron', 7: slotmask (see below) // The shader allows to set 7 different types of masks
|
||||
|
||||
0 = CGCW - a very light generic mask pattern
|
||||
1 - 4 = Lottes masks, 4 different types of masks that simulate a shadow mask more or less.
|
||||
5 - 6 = Trinitron. These are very effective mask types, that closely resemble the appearance of Trinitron's aperture grill. "5" is a finer version, mostly for use on 1080p, "6" is a more coarse version, mostly for use on 4K resolution.
|
||||
7 = slotmask, to be used in conjunction with the additional slotmask parameters.
|
||||
|
||||
Mask types 1 to 6 strength can be set with these two parameters:
|
||||
|
||||
Lottes maskDark // lower values generally make the mask appear more strongly
|
||||
Lottes maskLight // higher values generally make the mask appear more strongly
|
||||
|
||||
When using "7" slotmask, below parameters need to be set:
|
||||
|
||||
CRT Mask Size (2.0 is nice in 4k) // set to 1 for 1080p, 2 for 4K resolution
|
||||
Slot Mask Strength // Overall strength of the slot mask. Good values are around 0.5
|
||||
Slot Mask Width // Determines the horizontal size of the slotmask pattern. Use 2 or 3 for 1080p, 4-6 for 4K resolution.
|
||||
Slot Mask Height: 2x1 or 4x1" // Determines the vertical size of the slotmask pattern. Use 1 for 1080p, or 2 for 4K resolution.
|
||||
|
||||
Finally there's a parameter that influences the look of mask 5 - 7.
|
||||
Mask 5&6 cutoff // This determines how soon black appears between pixels for colors that are close to the R, G, or B primaries. This is suitable for both Trinitron and Slotmask. Default is 0.2. Higher values create a quicker cutoff to black between these pixels.
|
||||
|
||||
-----------------------
|
||||
# Color Temperature % #
|
||||
-----------------------
|
||||
|
||||
Each CRT monitor has a "whitepoint" setting, which influences how warm or cold the colors will look. The whitepoint setting differed quite a bit between different CRT models. Some had a 5000K (D50) whitepoint, i.e. "warm" colors, and some had a 9300K whitepoint,i.e. very "cold" colors. Most will sit somewhere in between, with today's standard being 6500K (D65). Note that a warmer setting tends the greys noticeably to a more yellowish brown, while the colder setting moves it to a more blueish grey.
|
||||
|
||||
At setting 0 the "color temperature %" is equivalent to the D65 whitepoint, let's say "neutral". Lower it to move towards the more warm 5000K point, or raise it to move it more towards the 9300K cold point.
|
||||
|
||||
-------------------
|
||||
# PVM Like Colors #
|
||||
-------------------
|
||||
|
||||
PVM Like Colors // This is a bit of candy that tries to simulate some of the color aberrations that appear with Sony PVM and BVM monitors.
|
||||
|
||||
-------------------
|
||||
# LUT Colors #
|
||||
-------------------
|
||||
|
||||
The shader has two ways to simulating "CRT Colors". LUT colors and CRT Color Profiles. LUT colors use lookup tables to transform the sRGB color profile to something more close to CRT colors. These LUTs come from varying sources, and the accuracy regarding CRT color simulation is a bit of an unknown, but at the least they provide some nice alternative color schemes which you may like.
|
||||
|
||||
|
||||
--------------------- ---------------
|
||||
# CRT Color Profile # & # Color Space #
|
||||
--------------------- ---------------
|
||||
|
||||
"CRT colors" changes the default colors to something more close to what the RGB Phosphors in CRTs produce.
|
||||
|
||||
These profiles are about subtle changes, but if you were used to the display of CRTs you may remember the display having more vivid greens, softer yellows and red, etc. It all depends on the type of CRT you were looking at, but admittedly CRT colors are different from the default sRGB color gamut that is prevalent in today's LCD screens.
|
||||
|
||||
The CRT colors are based on research of the CIE chromaticity coordinates of the most common phosphors used back in the day. Therefore we ended up with 3 "specs" which are EBU standard phosphors, P22-RGB phosphors and the SMPTE-C standard. These three profiles can be selected under "CRT colors" as number 1, 2 and 3.
|
||||
|
||||
Then there are two additional "calibrated" profiles that actually quite closely match a Philips based CRT monitor and a Trinitron monitor. They are profile number 4 and 5.
|
||||
|
||||
Some more information on these profiles can be read below.
|
||||
|
||||
The main drawback currently is that Phosphor color primaries are partly outside the sRGB spectrum, such that for these profiles a "Wide Color Gamut" monitor is needed / recommended. This is what the "Color space" option is for. If you happen to own a monitor that is able to display DCI-P3 color gamut, then set this option to "1". Option "2" is for AdobeRGB and "3" for Rec. 2020. DCI-P3 is verified to be quite accurate.
|
||||
|
||||
|
||||
In conclusion:
|
||||
|
||||
The good news is that we've got "CRT colors" largely covered now with the correct specs and two "quite accurate" calibrated profiles. The bad news is that with a default sRGB monitor the profiles will be more or less clipped and look wrong, depending on the content. Then we have some good news, as it seems that DCI-P3 or some other wide color gamut will be part of the HDR-500+ spec (see here: https://displayhdr.org/wp-content/uploads/2019/02/DisplayHDR_SpecChart_Rows_190219.jpg ) So within a few years wide color gamut should become mainstream in monitors. The question remains whether for HDR-500+ certified monitors this wide color gamut can be enabled by the user or emulator, or whether it will be only available in HDR content encoded mode. Time will tell.
|
||||
|
||||
Lastly, let's not forget we are talking about subtle differences from the default sRGB colors here. Let's just say you have to be slightly OCD on CRT tech to really appreciate the difference :-)
|
||||
|
||||
For those interested below is some additional information on each of the profiles and the specific chromaticity values used. This is purely additional information, there is no need (or possibility) to do anything with these in the shader settings.
|
||||
|
||||
|
||||
"CRT Colors" for CRT-Guest-Dr-Venom -- Additional information.
|
||||
|
||||
3 x spec
|
||||
2 x calibration
|
||||
|
||||
Specifications for three standards
|
||||
|
||||
1. EBU Standard Phosphors
|
||||
// Amongst others used in Sony BVMs and Higher-end PVMs
|
||||
// Tolerances are described in the E.B.U. standard reference document "E.B.U. standard for chromaticity tolerances for studio monitors" tech-3213-E.
|
||||
// PVM-1440QM service manual quotes 0.01 as tolerance on the RGB CIE coordinates.
|
||||
|
||||
xb0 = "150.000000"
|
||||
xg0 = "290.000000"
|
||||
xr0 = "640.000000"
|
||||
yb0 = "60.000000"
|
||||
yg0 = "600.000000"
|
||||
yr0 = "330.000000"
|
||||
|
||||
Whitepoint is D65
|
||||
|
||||
X 95,04 --> Xw0 950.4
|
||||
Y 100 --> Yw0 1000
|
||||
Z 108,88 --> Zw0 1088.8
|
||||
|
||||
2. P22 Phosphors
|
||||
// These phosphors are often quoted as the "default" phosphors used in CRTs
|
||||
// Also used in lower-end PVMs, see Sony PVM-20M4E 20M2E Colour Video Monitor.pdf
|
||||
// These can still be bought :-) https://www.phosphor-technology.com/crt-phosphors/ -- includes CIE coordinates.
|
||||
|
||||
xb0 = "148.000000"
|
||||
xg0 = "310.000000"
|
||||
xr0 = "647.000000"
|
||||
yb0 = "62.000000"
|
||||
yg0 = "594.000000"
|
||||
yr0 = "343.000000"
|
||||
|
||||
3. SMPTE-C
|
||||
// Spec for most of America.
|
||||
// I have forgone on the 1953 NTSC standard, as apart from very few early color TV's the 1953 NTSC standard was never actually used. Instead less saturated primaries were used to achieve brighter screens.
|
||||
// Taken from the WIKI on NTSC (https://en.wikipedia.org/wiki/NTSC) In 1968-69 the Conrac Corp., working with RCA, defined a set of controlled phosphors for use in broadcast color picture video monitors. This specification survives today as the SMPTE "C" phosphor specification:
|
||||
|
||||
xb0 = "155.000000"
|
||||
xg0 = "310.000000"
|
||||
xr0 = "630.000000"
|
||||
yb0 = "70.000000"
|
||||
yg0 = "595.000000"
|
||||
yr0 = "340.000000"
|
||||
|
||||
Whitepoint is D65
|
||||
|
||||
X 95,04 --> Xw0 950.4
|
||||
Y 100 --> Yw0 1000
|
||||
Z 108,88 --> Zw0 1088.8
|
||||
|
||||
|
||||
4. Calibrated profile for Philips CRT monitors. Of course an approximation, but I'm pleased with the "quite accurate" results.
|
||||
// Manually calibrated and compared to real Philips based CRT monitors, running side by side with the shader on a 10-bit DCI-P3 gamut panel. This calibrated CRT profile covers amongst others Philips CM8533, Philips VS-0080, and Commodore 1084.
|
||||
// Note the whitepoint is significantly different from D65. It's closer to 6100K, but clearly not on the blackbody curve. Possibly an ISO-line target, given the slight hue on the whitepoint. Other than that it could be aging / whitepoint drift. I compared four CRT monitors, one of them in very mint condition, and they all have this slight hue on the whitepoint, so I would guess this is how they came out of the factory. But then again since these things are now getting close to 30 years old, who knows? Either way the profile should be good: factory out or true to life aged CRTs... :D.
|
||||
// It's important this specific whitepoint is used in the shader or the colors will not be accurate.
|
||||
// Also it's important to note that this profile should be used with "Gamma Out" at 2.25 or the colors will be less accurate.
|
||||
|
||||
xb0 = "154.000000"
|
||||
xg0 = "300.000000"
|
||||
xr0 = "635.000000"
|
||||
yb0 = "60.000000"
|
||||
yg0 = "620.000000"
|
||||
yr0 = "339.000000"
|
||||
|
||||
Whitepoint:
|
||||
Xw0 = "910.000000"
|
||||
Yw0 = "1000.000000"
|
||||
Zw0 = "960.000000"
|
||||
|
||||
|
||||
5. Calibrated profile for Sony Trinitron Monitor.
|
||||
// In a similar fashion as the Philips CRT based profile, this is a manually calibrated profile for a Sony Trinitron monitor, model KX-14CP1.
|
||||
// This monitor uses a Whitepoint that is close to 9300K. The Z value in the calibration process has been raised to the point where the "blue-ishness" of the white matches. To achieve further 9300K white, I guess one has to raise the hardware whitepoint of the host PC monitor...
|
||||
// It's important this specific whitepoint is used in the shader or the colors will not be accurate.
|
||||
// Also it's important to note that this profile should be used with "Gamma Out" at 2.25 or the colors will be less accurate.
|
||||
|
||||
xb0 = "152.000000"
|
||||
xg0 = "279.000000"
|
||||
xr0 = "647.000000"
|
||||
yb0 = "60.000000"
|
||||
yg0 = "635.000000"
|
||||
yr0 = "335.000000"
|
||||
|
||||
Whitepoint:
|
||||
Xw0 = "903.000000"
|
||||
Yw0 = "1000.000000"
|
||||
Zw0 = "1185.000000"
|
||||
|
||||
End :)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -23,19 +23,7 @@
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float SW;
|
||||
float AR;
|
||||
float PR;
|
||||
float AG;
|
||||
float PG;
|
||||
float AB;
|
||||
float PB;
|
||||
float sat;
|
||||
float GTH;
|
||||
float SW, AR, PR, AG, PG, AB, PB, sat;
|
||||
} params;
|
||||
|
||||
#pragma parameter SW "Afterglow switch ON/OFF" 1.0 0.0 1.0 1.0
|
||||
@ -46,7 +34,17 @@ layout(push_constant) uniform Push
|
||||
#pragma parameter AB "Afterglow Blue" 0.07 0.0 1.0 0.01
|
||||
#pragma parameter PB "Persistence Blue" 0.05 0.0 1.0 0.01
|
||||
#pragma parameter sat "Afterglow saturation" 0.10 0.0 1.0 0.01
|
||||
#pragma parameter GTH "Afterglow threshold" 5.0 0.0 255.0 1.0
|
||||
|
||||
#define SW params.SW
|
||||
#define AR params.AR
|
||||
#define PR params.PR
|
||||
#define AG params.AG
|
||||
#define PG params.PG
|
||||
#define AB params.AB
|
||||
#define PB params.PB
|
||||
#define sat params.sat
|
||||
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
@ -75,30 +73,39 @@ layout(set = 0, binding = 6) uniform sampler2D OriginalHistory4;
|
||||
layout(set = 0, binding = 7) uniform sampler2D OriginalHistory5;
|
||||
layout(set = 0, binding = 8) uniform sampler2D OriginalHistory6;
|
||||
|
||||
#define eps 1e-4
|
||||
#define Prev1Texture OriginalHistory1
|
||||
#define Prev2Texture OriginalHistory2
|
||||
#define Prev3Texture OriginalHistory3
|
||||
#define Prev4Texture OriginalHistory4
|
||||
#define Prev5Texture OriginalHistory5
|
||||
#define Prev6Texture OriginalHistory6
|
||||
|
||||
#define TEX0 vTexCoord
|
||||
|
||||
#define eps 1e-3
|
||||
|
||||
vec3 afterglow(float number)
|
||||
{
|
||||
return vec3(params.AR, params.AG, params.AB)*exp2(-vec3(params.PR, params.PG, params.PB)*vec3(number*number));
|
||||
return vec3(AR, AG, AB)*exp2(-vec3(PR, PG, PB)*vec3(number*number));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 color = texture(Source, vTexCoord.xy).rgb;
|
||||
vec3 color1 = texture(OriginalHistory1, vTexCoord.xy).rgb * afterglow(1.0);
|
||||
vec3 color2 = texture(OriginalHistory2, vTexCoord.xy).rgb * afterglow(2.0);
|
||||
vec3 color3 = texture(OriginalHistory3, vTexCoord.xy).rgb * afterglow(3.0);
|
||||
vec3 color4 = texture(OriginalHistory4, vTexCoord.xy).rgb * afterglow(4.0);
|
||||
vec3 color5 = texture(OriginalHistory5, vTexCoord.xy).rgb * afterglow(5.0);
|
||||
vec3 color6 = texture(OriginalHistory6, vTexCoord.xy).rgb * afterglow(6.0);
|
||||
vec3 color = COMPAT_TEXTURE(Source, TEX0.xy).rgb;
|
||||
vec3 color1 = COMPAT_TEXTURE(Prev1Texture, TEX0.xy).rgb * afterglow(1.0);
|
||||
vec3 color2 = COMPAT_TEXTURE(Prev2Texture, TEX0.xy).rgb * afterglow(2.0);
|
||||
vec3 color3 = COMPAT_TEXTURE(Prev3Texture, TEX0.xy).rgb * afterglow(3.0);
|
||||
vec3 color4 = COMPAT_TEXTURE(Prev4Texture, TEX0.xy).rgb * afterglow(4.0);
|
||||
vec3 color5 = COMPAT_TEXTURE(Prev5Texture, TEX0.xy).rgb * afterglow(5.0);
|
||||
vec3 color6 = COMPAT_TEXTURE(Prev6Texture, TEX0.xy).rgb * afterglow(6.0);
|
||||
|
||||
vec3 glow = color1 + color2 + color3 + color4 + color5 + color6;
|
||||
|
||||
float l = length(glow);
|
||||
glow = normalize(pow(glow + vec3(eps), vec3(params.sat)))*l;
|
||||
glow = normalize(pow(glow + vec3(eps), vec3(sat)))*l;
|
||||
|
||||
float w = 1.0;
|
||||
if ((color.r + color.g + color.b) > params.GTH/255.0) w = 0.0;
|
||||
if ((color.r + color.g + color.b) > 7.0/255.0) w = 0.0;
|
||||
|
||||
FragColor = vec4(color + params.SW*w*glow,1.0);
|
||||
FragColor = vec4(color + SW*w*glow,1.0);
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
#version 450
|
||||
|
||||
/*
|
||||
Average Luminance Shader
|
||||
Average Luminance Shader, Smart Smoothing Difference Shader
|
||||
|
||||
Copyright (C) 2018 guest(r) - guest.r@gmail.com
|
||||
Copyright (C) 2018-2019 guest(r) - guest.r@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@ -25,13 +25,16 @@
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float grade;
|
||||
float STH;
|
||||
} params;
|
||||
|
||||
#pragma parameter grade "Raster Bloom Grade" 0.65 0.10 1.0 0.05
|
||||
#pragma parameter STH "Smart Smoothing Threshold" 0.7 0.4 1.2 0.05
|
||||
|
||||
#define STH params.STH
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define SourceSize params.SourceSize
|
||||
#define InputSize SourceSize
|
||||
#define TEX0 vTexCoord
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
@ -46,32 +49,61 @@ layout(location = 0) out vec2 vTexCoord;
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
vTexCoord = TexCoord * 1.0001;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
layout(set = 0, binding = 3) uniform sampler2D WhitePointPass;
|
||||
|
||||
#define PassPrev2Texture WhitePointPass
|
||||
|
||||
float df (vec3 A, vec3 B)
|
||||
{
|
||||
float diff = length(A-B);
|
||||
float luma = clamp(length(0.5*min(A,B) + 0.25*(A+B) + 1e-8), 0.0001, 1.0);
|
||||
float diff1 = diff/luma;
|
||||
return 1.0 - clamp(7.0*(max(1.5*diff,diff1)-STH), 0.0, 0.9999);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float xtotal = floor(params.SourceSize.x/32.0);
|
||||
float ytotal = floor(params.SourceSize.y/32.0);
|
||||
float xtotal = floor(InputSize.x/64.0);
|
||||
float ytotal = floor(InputSize.y/64.0);
|
||||
|
||||
float ltotal = 0.0;
|
||||
vec2 dx = vec2(params.SourceSize.z, 0.0)*32.0;
|
||||
vec2 dy = vec2(0.0, params.SourceSize.w)*32.0;
|
||||
|
||||
vec2 dx = vec2(SourceSize.z, 0.0)*64.0;
|
||||
vec2 dy = vec2(0.0, SourceSize.w)*64.0;
|
||||
vec2 offset = 0.25*(dx+dy);
|
||||
|
||||
for (float i = 0.0; i <= xtotal; i++)
|
||||
{
|
||||
for (float j = 0.0; j <= ytotal; j++)
|
||||
{
|
||||
ltotal += length(textureLod(Source, i*dx + j*dy, 5.0).rgb);
|
||||
ltotal+= max(0.25, length(textureLod(Source, i*dx + j*dy + offset, 6.0).rgb));
|
||||
}
|
||||
}
|
||||
|
||||
ltotal = inversesqrt(3.0)*ltotal / ((xtotal+1.0)*(ytotal+1.0));
|
||||
ltotal = 0.577350269 * ltotal / ((xtotal+1.0)*(ytotal+1.0));
|
||||
|
||||
FragColor = vec4(pow(ltotal, params.grade));
|
||||
dx = vec2(SourceSize.z, 0.0);
|
||||
dy = vec2(0.0, SourceSize.w);
|
||||
|
||||
vec3 l1 = COMPAT_TEXTURE(PassPrev2Texture, TEX0.xy -dx).xyz;
|
||||
vec3 ct = COMPAT_TEXTURE(PassPrev2Texture, TEX0.xy ).xyz;
|
||||
vec3 r1 = COMPAT_TEXTURE(PassPrev2Texture, TEX0.xy +dx).xyz;
|
||||
vec3 t1 = COMPAT_TEXTURE(PassPrev2Texture, TEX0.xy -dy).xyz;
|
||||
vec3 b1 = COMPAT_TEXTURE(PassPrev2Texture, TEX0.xy +dy).xyz;
|
||||
|
||||
float dl = df(ct, l1);
|
||||
float dr = df(ct, r1);
|
||||
float dt = df(ct, t1);
|
||||
float db = df(ct, b1);
|
||||
|
||||
float resx = dl; float resy = dr; float resz = floor(9.0*dt)/10.0 + floor(9.0*db)/100.0;
|
||||
|
||||
FragColor = vec4(resx,resy,resz,pow(ltotal, 0.65));
|
||||
}
|
63
crt/shaders/guest/avg-lum0.slang
Normal file
63
crt/shaders/guest/avg-lum0.slang
Normal file
@ -0,0 +1,63 @@
|
||||
#version 450
|
||||
|
||||
// Avg. Luminance Smoothing
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
} params;
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
} global;
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D OriginalHistory1;
|
||||
layout(set = 0, binding = 3) uniform sampler2D OriginalHistory2;
|
||||
layout(set = 0, binding = 4) uniform sampler2D OriginalHistory3;
|
||||
layout(set = 0, binding = 5) uniform sampler2D OriginalHistory4;
|
||||
layout(set = 0, binding = 6) uniform sampler2D OriginalHistory5;
|
||||
layout(set = 0, binding = 7) uniform sampler2D OriginalHistory6;
|
||||
layout(set = 0, binding = 8) uniform sampler2D OriginalHistory7;
|
||||
|
||||
#define PrevTexture OriginalHistory1
|
||||
#define Prev1Texture OriginalHistory2
|
||||
#define Prev2Texture OriginalHistory3
|
||||
#define Prev3Texture OriginalHistory4
|
||||
#define Prev4Texture OriginalHistory5
|
||||
#define Prev5Texture OriginalHistory6
|
||||
#define Prev6Texture OriginalHistory7
|
||||
|
||||
#define TEX0 vTexCoord
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 color = COMPAT_TEXTURE(PrevTexture, TEX0.xy).rgb;
|
||||
color+= COMPAT_TEXTURE(Prev6Texture, TEX0.xy).rgb;
|
||||
color+= COMPAT_TEXTURE(Prev5Texture, TEX0.xy).rgb;
|
||||
color+= COMPAT_TEXTURE(Prev4Texture, TEX0.xy).rgb;
|
||||
color+= COMPAT_TEXTURE(Prev3Texture, TEX0.xy).rgb;
|
||||
color+= COMPAT_TEXTURE(Prev2Texture, TEX0.xy).rgb;
|
||||
color+= COMPAT_TEXTURE(Prev1Texture, TEX0.xy).rgb;
|
||||
|
||||
FragColor = vec4(color/7.0,1.0);
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
#version 450
|
||||
|
||||
// Higher value, more centered glow.
|
||||
// Lower values might need more taps.
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
@ -13,8 +10,12 @@ layout(push_constant) uniform Push
|
||||
float GLOW_FALLOFF_H;
|
||||
} params;
|
||||
|
||||
// Higher value, more centered glow.
|
||||
// Lower values might need more taps.
|
||||
#pragma parameter TAPSH "H. Glow Radius" 4.0 1.0 10.0 1.0
|
||||
#pragma parameter GLOW_FALLOFF_H "Horizontal Glow Grade" 0.30 0.0 1.0 0.01
|
||||
#define TAPSH params.TAPSH
|
||||
#pragma parameter GLOW_FALLOFF_H "Horizontal Glow Grade" 0.30 0.00 1.0 0.01
|
||||
#define GLOW_FALLOFF_H params.GLOW_FALLOFF_H
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
@ -37,19 +38,22 @@ layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
#define kernel(x) exp(-params.GLOW_FALLOFF_H * (x) * (x))
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define SourceSize params.SourceSize
|
||||
|
||||
#define kernel(x) exp(-GLOW_FALLOFF_H * (x) * (x))
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 col = vec3(0.0);
|
||||
float dx = params.SourceSize.z;
|
||||
float dx = SourceSize.z;
|
||||
|
||||
float k_total = 0.;
|
||||
for (float i = -params.TAPSH; i <= params.TAPSH; i++)
|
||||
for (float i = -TAPSH; i <= TAPSH; i++)
|
||||
{
|
||||
float k = kernel(i);
|
||||
k_total += k;
|
||||
col += k * texture(Source, vTexCoord + vec2(float(i) * dx, 0.0)).rgb;
|
||||
col += k * COMPAT_TEXTURE(Source, vTexCoord + vec2(float(i) * dx, 0.0)).rgb;
|
||||
}
|
||||
FragColor = vec4(col / k_total, 1.0);
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
#version 450
|
||||
|
||||
// Higher value, more centered glow.
|
||||
// Lower values might need more taps.
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
@ -13,8 +10,13 @@ layout(push_constant) uniform Push
|
||||
float GLOW_FALLOFF_V;
|
||||
} params;
|
||||
|
||||
// Higher value, more centered glow.
|
||||
// Lower values might need more taps.
|
||||
// Parameter lines go here:
|
||||
#pragma parameter TAPSV "V. Glow Radius" 4.0 1.0 10.0 1.0
|
||||
#pragma parameter GLOW_FALLOFF_V "Vertical Glow Grade" 0.30 0.0 1.0 0.01
|
||||
#define TAPSV params.TAPSV
|
||||
#pragma parameter GLOW_FALLOFF_V "Vertical Glow Grade" 0.30 0.00 1.0 0.01
|
||||
#define GLOW_FALLOFF_V params.GLOW_FALLOFF_V
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
@ -37,19 +39,22 @@ layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
#define kernel(x) exp(-params.GLOW_FALLOFF_V * (x) * (x))
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define SourceSize params.SourceSize
|
||||
|
||||
#define kernel(x) exp(-GLOW_FALLOFF_V * (x) * (x))
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 col = vec3(0.0);
|
||||
float dy = params.SourceSize.w;
|
||||
float dy = SourceSize.w;
|
||||
|
||||
float k_total = 0.;
|
||||
for (float i = -params.TAPSV; i <= params.TAPSV; i++)
|
||||
for (float i = -TAPSV; i <= TAPSV; i++)
|
||||
{
|
||||
float k = kernel(i);
|
||||
k_total += k;
|
||||
col += k * texture(Source, vTexCoord + vec2(0.0, float(i) * dy)).rgb;
|
||||
col += k * COMPAT_TEXTURE(Source, vTexCoord + vec2(0.0, float(i) * dy)).rgb;
|
||||
}
|
||||
FragColor = vec4(col / k_total, 1.0);
|
||||
}
|
160
crt/shaders/guest/color-profiles.slang
Normal file
160
crt/shaders/guest/color-profiles.slang
Normal file
@ -0,0 +1,160 @@
|
||||
#version 450
|
||||
|
||||
/*
|
||||
CRT Color Profiles
|
||||
|
||||
Copyright (C) 2019 guest(r) and Dr. Venom
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
float CP, CS;
|
||||
} params;
|
||||
|
||||
#pragma parameter CP "CRT Color Profile" 0.0 -1.0 5.0 1.0
|
||||
#pragma parameter CS "Color Space: sRGB, DCI, Adobe, Rec.2020" 0.0 0.0 3.0 1.0
|
||||
|
||||
#define CP params.CP
|
||||
#define CS params.CS
|
||||
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define TEX0 vTexCoord
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
} global;
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
const mat3 Profile0 =
|
||||
mat3(
|
||||
0.412391, 0.212639, 0.019331,
|
||||
0.357584, 0.715169, 0.119195,
|
||||
0.180481, 0.072192, 0.950532
|
||||
);
|
||||
|
||||
const mat3 Profile1 =
|
||||
mat3(
|
||||
0.430554, 0.222004, 0.020182,
|
||||
0.341550, 0.706655, 0.129553,
|
||||
0.178352, 0.071341, 0.939322
|
||||
);
|
||||
|
||||
const mat3 Profile2 =
|
||||
mat3(
|
||||
0.396686, 0.210299, 0.006131,
|
||||
0.372504, 0.713766, 0.115356,
|
||||
0.181266, 0.075936, 0.967571
|
||||
);
|
||||
|
||||
const mat3 Profile3 =
|
||||
mat3(
|
||||
0.393521, 0.212376, 0.018739,
|
||||
0.365258, 0.701060, 0.111934,
|
||||
0.191677, 0.086564, 0.958385
|
||||
);
|
||||
|
||||
const mat3 Profile4 =
|
||||
mat3(
|
||||
0.392258, 0.209410, 0.016061,
|
||||
0.351135, 0.725680, 0.093636,
|
||||
0.166603, 0.064910, 0.850324
|
||||
);
|
||||
|
||||
const mat3 Profile5 =
|
||||
mat3(
|
||||
0.377923, 0.195679, 0.010514,
|
||||
0.317366, 0.722319, 0.097826,
|
||||
0.207738, 0.082002, 1.076960
|
||||
);
|
||||
|
||||
const mat3 ToSRGB =
|
||||
mat3(
|
||||
3.240970, -0.969244, 0.055630,
|
||||
-1.537383, 1.875968, -0.203977,
|
||||
-0.498611, 0.041555, 1.056972
|
||||
);
|
||||
|
||||
const mat3 ToDCI =
|
||||
mat3(
|
||||
2.725394, -0.795168, 0.041242,
|
||||
-1.018003, 1.689732, 0.022647,
|
||||
-0.440163, 0.022647, 1.100929
|
||||
);
|
||||
|
||||
const mat3 ToAdobe =
|
||||
mat3(
|
||||
2.041588, -0.969244, 0.013444,
|
||||
-0.565007, 1.875968, -0.11836,
|
||||
-0.344731, 0.041555, 1.015175
|
||||
);
|
||||
|
||||
const mat3 ToREC =
|
||||
mat3(
|
||||
1.716651, -0.666684, 0.017640,
|
||||
-0.355671, 1.616481, -0.042771,
|
||||
-0.253366, 0.015769, 0.942103
|
||||
);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 c = COMPAT_TEXTURE(Source, TEX0.xy).rgb;
|
||||
|
||||
float p;
|
||||
mat3 m_out;
|
||||
|
||||
if (CS == 0.0) { p = 2.4; m_out = ToSRGB; } else
|
||||
if (CS == 1.0) { p = 2.6; m_out = ToDCI; } else
|
||||
if (CS == 2.0) { p = 2.2; m_out = ToAdobe;} else
|
||||
if (CS == 3.0) { p = 2.4; m_out = ToREC; }
|
||||
|
||||
vec3 color = pow(c, vec3(p));
|
||||
|
||||
mat3 m_in = Profile0;
|
||||
|
||||
if (CP == 0.0) { m_in = Profile0; } else
|
||||
if (CP == 1.0) { m_in = Profile1; } else
|
||||
if (CP == 2.0) { m_in = Profile2; } else
|
||||
if (CP == 3.0) { m_in = Profile3; } else
|
||||
if (CP == 4.0) { m_in = Profile4; } else
|
||||
if (CP == 5.0) { m_in = Profile5; }
|
||||
|
||||
color = m_in*color;
|
||||
color = m_out*color;
|
||||
|
||||
color = pow(color, vec3(1.0/p));
|
||||
|
||||
if (CP == -1.0) color = c;
|
||||
|
||||
FragColor = vec4(color,1.0);
|
||||
}
|
@ -25,82 +25,92 @@
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OutputSize;
|
||||
float TATE; // Screen orientation
|
||||
float IOS; // Smart Integer Scaling
|
||||
float OS; // Do overscan
|
||||
float BLOOM; // Bloom overscan percentage
|
||||
float brightboost; // adjust brightness
|
||||
float saturation; // 1.0 is normal saturation
|
||||
float gsl; // Alternate scanlines
|
||||
float scanline; // scanline param, vertical sharpness
|
||||
float beam_min; // dark area beam min - wide
|
||||
float beam_max; // bright area beam max - narrow
|
||||
float h_sharp; // pixel sharpness
|
||||
float s_sharp; // substractive sharpness
|
||||
float csize; // corner size
|
||||
float warpX; // Curvature X
|
||||
float warpY; // Curvature Y
|
||||
float glow; // Glow Strength
|
||||
float shadowMask; // Mask Style
|
||||
float maskDark; // Dark "Phosphor"
|
||||
float maskLight; // Light "Phosphor"
|
||||
float CGWG; // CGWG Mask Strength
|
||||
float GTW; // Gamma tweak
|
||||
float gamma_out; // output gamma
|
||||
float TATE, IOS, OS, BLOOM, brightboost, gsl, scanline1, scanline2, beam_min, beam_max, beam_size,
|
||||
h_sharp, s_sharp, h_smart, csize, bsize, warpX, warpY, glow, shadowMask, masksize, vertmask,
|
||||
slotmask, slotwidth, double_slot, mcut, maskDark, maskLight, CGWG, GTW, gamma_out;
|
||||
} params;
|
||||
|
||||
#pragma parameter TATE "TATE Mode" 0.0 0.0 1.0 1.0
|
||||
#define TATE params.TATE
|
||||
#pragma parameter IOS "Smart Integer Scaling" 0.0 0.0 1.0 1.0
|
||||
#define IOS params.IOS
|
||||
#pragma parameter OS "R. Bloom Overscan Mode" 2.0 0.0 2.0 1.0
|
||||
#define OS params.OS
|
||||
#define TATE params.TATE // Screen orientation
|
||||
#pragma parameter IOS "Smart Integer Scaling: 1.0:Y, 2.0:'X'+Y" 0.0 0.0 2.0 1.0
|
||||
#define IOS params.IOS // Smart Integer Scaling
|
||||
#pragma parameter OS "R. Bloom Overscan Mode" 1.0 0.0 2.0 1.0
|
||||
#define OS params.OS // Do overscan
|
||||
#pragma parameter BLOOM "Raster bloom %" 0.0 0.0 20.0 1.0
|
||||
#define BLOOM params.BLOOM
|
||||
#pragma parameter brightboost "Bright boost" 1.10 0.50 2.00 0.01
|
||||
#define brightboost params.brightboost
|
||||
#pragma parameter saturation "Saturation adjustment" 1.0 0.1 2.0 0.05
|
||||
#define saturation params.saturation
|
||||
#pragma parameter gsl "Alternate scanlines" 0.0 0.0 1.0 1.0
|
||||
#define gsl params.gsl
|
||||
#pragma parameter scanline "Scanline adjust" 8.0 1.0 12.0 1.0
|
||||
#define scanline params.scanline
|
||||
#pragma parameter beam_min "Scanline dark" 1.30 0.5 2.0 0.05
|
||||
#define beam_min params.beam_min
|
||||
#pragma parameter beam_max "Scanline bright" 1.0 0.5 2.0 0.05
|
||||
#define beam_max params.beam_max
|
||||
#pragma parameter h_sharp "Horizontal sharpness" 5.0 1.5 20.0 0.25
|
||||
#define h_sharp params.h_sharp
|
||||
#pragma parameter s_sharp "Substractive sharpness" 0.0 0.0 0.20 0.01
|
||||
#define s_sharp params.s_sharp
|
||||
#pragma parameter csize "Corner size" 0.0 0.0 0.05 0.01
|
||||
#define csize params.csize
|
||||
#define BLOOM params.BLOOM // Bloom overscan percentage
|
||||
#pragma parameter brightboost "Bright boost" 1.35 0.50 2.00 0.01
|
||||
#define brightboost params.brightboost // adjust brightness
|
||||
#pragma parameter gsl "Scanline Type" 0.0 0.0 2.0 1.0
|
||||
#define gsl params.gsl // Alternate scanlines
|
||||
#pragma parameter scanline1 "Scanline beam shape low" 8.0 1.0 15.0 1.0
|
||||
#define scanline1 params.scanline1 // scanline param, vertical sharpness
|
||||
#pragma parameter scanline2 "Scanline beam shape high" 8.0 5.0 23.0 1.0
|
||||
#define scanline2 params.scanline2 // scanline param, vertical sharpness
|
||||
#pragma parameter beam_min "Scanline dark" 1.35 0.5 2.0 0.05
|
||||
#define beam_min params.beam_min // dark area beam min - narrow
|
||||
#pragma parameter beam_max "Scanline bright" 1.05 0.5 2.0 0.05
|
||||
#define beam_max params.beam_max // bright area beam max - wide
|
||||
#pragma parameter beam_size "Increased bright scanline beam" 0.65 0.0 1.0 0.05
|
||||
#define beam_size params.beam_size // increased max. beam size
|
||||
#pragma parameter h_sharp "Horizontal sharpness" 5.25 1.5 20.0 0.25
|
||||
#define h_sharp params.h_sharp // pixel sharpness
|
||||
#pragma parameter s_sharp "Substractive sharpness" 0.05 0.0 0.20 0.01
|
||||
#define s_sharp params.s_sharp // substractive sharpness
|
||||
#pragma parameter h_smart "Smart Horizontal Smoothing" 0.0 0.0 1.0 0.1
|
||||
#define h_smart params.h_smart // smart horizontal smoothing
|
||||
#pragma parameter csize "Corner size" 0.0 0.0 0.07 0.01
|
||||
#define csize params.csize // corner size
|
||||
#pragma parameter bsize "Border smoothness" 600.0 100.0 600.0 25.0
|
||||
#define bsize params.bsize // border smoothness
|
||||
#pragma parameter warpX "CurvatureX (default 0.03)" 0.0 0.0 0.125 0.01
|
||||
#define warpX params.warpX
|
||||
#define warpX params.warpX // Curvature X
|
||||
#pragma parameter warpY "CurvatureY (default 0.04)" 0.0 0.0 0.125 0.01
|
||||
#define warpY params.warpY
|
||||
#pragma parameter glow "Glow Strength" 0.04 0.0 0.5 0.01
|
||||
#define glow params.glow
|
||||
#pragma parameter shadowMask "Mask Style (0 = CGWG)" 0.0 -1.0 5.0 1.0
|
||||
#define shadowMask params.shadowMask
|
||||
#pragma parameter maskDark "Lottes maskDark" 0.5 0.0 2.0 0.1
|
||||
#define maskDark params.maskDark
|
||||
#pragma parameter maskLight "Lottes maskLight" 1.5 0.0 2.0 0.1
|
||||
#define maskLight params.maskLight
|
||||
#pragma parameter CGWG "CGWG Mask Str." 0.4 0.0 1.0 0.05
|
||||
#define CGWG params.CGWG
|
||||
#pragma parameter GTW "Gamma Tweak" 1.10 0.5 1.5 0.01
|
||||
#define GTW params.GTW
|
||||
#pragma parameter gamma_out "Gamma out" 2.4 1.0 3.0 0.05
|
||||
#define gamma_out params.gamma_out
|
||||
#define warpY params.warpY // Curvature Y
|
||||
#pragma parameter glow "Glow Strength" 0.02 0.0 0.5 0.01
|
||||
#define glow params.glow // Glow Strength
|
||||
#pragma parameter shadowMask "CRT Mask: 0:CGWG, 1-4:Lottes, 5-6:'Trinitron'" 0.0 -1.0 7.0 1.0
|
||||
#define shadowMask params.shadowMask // Mask Style
|
||||
#pragma parameter masksize "CRT Mask Size (2.0 is nice in 4k)" 1.0 1.0 2.0 1.0
|
||||
#define masksize params.masksize // Mask Size
|
||||
#pragma parameter vertmask "PVM Like Colors" 0.0 0.0 0.25 0.01
|
||||
#define vertmask params.vertmask // Vertical mask
|
||||
#pragma parameter slotmask "Slot Mask Strength" 0.0 0.0 1.0 0.05
|
||||
#define slotmask params.slotmask // Slot Mask ON/OFF
|
||||
#pragma parameter slotwidth "Slot Mask Width" 2.0 2.0 6.0 0.5
|
||||
#define slotwidth params.slotwidth // Slot Mask Width
|
||||
#pragma parameter double_slot "Slot Mask Height: 2x1 or 4x1" 1.0 1.0 2.0 1.0
|
||||
#define double_slot params.double_slot // Slot Mask Height
|
||||
#pragma parameter mcut "Mask 5&6 cutoff" 0.2 0.0 0.5 0.05
|
||||
#define mcut params.mcut // Mask 5&6 cutoff
|
||||
#pragma parameter maskDark "Lottes maskDark" 0.5 0.0 2.0 0.05
|
||||
#define maskDark params.maskDark // Dark "Phosphor"
|
||||
#pragma parameter maskLight "Lottes maskLight" 1.5 0.0 2.0 0.05
|
||||
#define maskLight params.maskLight // Light "Phosphor"
|
||||
#pragma parameter CGWG "CGWG Mask Str." 0.3 0.0 1.0 0.05
|
||||
#define CGWG params.CGWG // CGWG Mask Strength
|
||||
#pragma parameter GTW "Gamma Tweak" 1.05 0.5 1.5 0.01
|
||||
#define GTW params.GTW // Gamma tweak
|
||||
#pragma parameter gamma_out "Gamma out" 2.4 1.0 3.5 0.05
|
||||
#define gamma_out params.gamma_out // output gamma
|
||||
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define TEX0 vTexCoord
|
||||
#define InputSize SourceSize
|
||||
#define TextureSize SourceSize
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
} global;
|
||||
|
||||
#define SourceSize global.SourceSize
|
||||
#define OutputSize global.OutputSize
|
||||
#define gl_FragCoord (vTexCoord * OutputSize.xy)
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
@ -109,43 +119,57 @@ layout(location = 0) out vec2 vTexCoord;
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord * 1.0001;
|
||||
vTexCoord = TexCoord * 1.00001;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
layout(set = 0, binding = 3) uniform sampler2D lum_pass;
|
||||
layout(set = 0, binding = 4) uniform sampler2D linearize_pass;
|
||||
layout(set = 0, binding = 3) uniform sampler2D LinearizePass;
|
||||
layout(set = 0, binding = 4) uniform sampler2D AvgLumPass;
|
||||
|
||||
#define Texture Source
|
||||
#define PassPrev3Texture LinearizePass
|
||||
#define PassPrev4Texture AvgLumPass
|
||||
|
||||
#define eps 1e-10
|
||||
|
||||
float b_min = 1.0 + 7.0*(beam_min - 0.5)*0.666666666;
|
||||
float b_max = 1.0 + 7.0*(beam_max - 0.5)*0.666666666;
|
||||
float scn_s = 0.3 + 0.7*(scanline - 1.0)*0.090909090;
|
||||
float st(float x, float scanline)
|
||||
{
|
||||
return exp2(-scanline*x*x);
|
||||
}
|
||||
|
||||
vec3 sw(float x, vec3 color)
|
||||
vec3 sw0(vec3 x, vec3 color, float scanline)
|
||||
{
|
||||
vec3 tmp = mix(vec3(beam_min),vec3(beam_max), color);
|
||||
vec3 ex = vec3(x)*tmp;
|
||||
vec3 ex = x*tmp;
|
||||
return exp2(-scanline*ex*ex);
|
||||
}
|
||||
|
||||
vec3 sw2(float x, vec3 c)
|
||||
vec3 sw1(vec3 x, vec3 color, float scanline)
|
||||
{
|
||||
vec3 s = mix(vec3(b_min), vec3(b_max), c);
|
||||
return clamp(smoothstep(vec3(0.0), vec3(scn_s), pow(vec3(x),s)), 0.0001, 1.0);
|
||||
float mx = max(max(color.r, color.g),color.b);
|
||||
x = mix (x, beam_min*x, max(x-0.4*mx,0.0));
|
||||
vec3 tmp = mix(vec3(1.2*beam_min),vec3(beam_max), color);
|
||||
vec3 ex = x*tmp;
|
||||
float br = clamp(0.8*beam_min - 1.0, 0.2, 0.45);
|
||||
return exp2(-scanline*ex*ex)/(1.0-br+br*color);
|
||||
}
|
||||
|
||||
// Shadow mask (mostly from PD Lottes shader).
|
||||
vec3 Mask(vec2 pos)
|
||||
vec3 sw2(vec3 x, vec3 color, float scanline)
|
||||
{
|
||||
vec3 tmp = mix(vec3(2.75*beam_min),vec3(beam_max), color);
|
||||
tmp = mix(vec3(beam_max), tmp, pow(x, vec3(max(max(color.r, color.g),color.b)+0.3)));
|
||||
vec3 ex = x*tmp;
|
||||
return exp2(-scanline*ex*ex)/(0.6 + 0.4*color);
|
||||
}
|
||||
|
||||
// Shadow mask (1-4 from PD CRT Lottes shader).
|
||||
vec3 Mask(vec2 pos, vec3 c)
|
||||
{
|
||||
pos = floor(pos/masksize);
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
float mf = floor(mod(pos.x,2.0));
|
||||
float mf2 = floor(mod(pos.x + pos.y,2.0));
|
||||
float mc = 1.0 - CGWG;
|
||||
float mc2 = mc * 0.7;
|
||||
|
||||
// No mask
|
||||
if (shadowMask == -1.0)
|
||||
@ -153,18 +177,13 @@ vec3 Mask(vec2 pos)
|
||||
mask = vec3(1.0);
|
||||
}
|
||||
|
||||
// Light mask.
|
||||
else if (shadowMask == 5.0)
|
||||
{
|
||||
if (mf2 == 0.0) { mask = vec3(1.0); }
|
||||
else { mask = vec3(mc2); }
|
||||
}
|
||||
|
||||
// Phosphor.
|
||||
else if (shadowMask == 0.0)
|
||||
{
|
||||
if (mf == 0.0) { mask.r = 1.0; mask.g = mc; mask.b = 1.0; }
|
||||
else { mask.r = mc; mask.g = 1.0; mask.b = mc; }
|
||||
pos.x = fract(pos.x*0.5);
|
||||
float mc = 1.0 - CGWG;
|
||||
if (pos.x < 0.5) { mask.r = 1.1; mask.g = mc; mask.b = 1.1; }
|
||||
else { mask.r = mc; mask.g = 1.1; mask.b = mc; }
|
||||
}
|
||||
|
||||
// Very compressed TV style shadow mask.
|
||||
@ -183,6 +202,7 @@ vec3 Mask(vec2 pos)
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
|
||||
mask*=line;
|
||||
}
|
||||
|
||||
@ -219,9 +239,63 @@ vec3 Mask(vec2 pos)
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// Alternate mask 5
|
||||
else if (shadowMask == 5.0)
|
||||
{
|
||||
float mx = max(max(c.r,c.g),c.b);
|
||||
vec3 maskTmp = vec3( min( 1.25*max(mx-mcut,0.0)/(1.0-mcut) ,maskDark + 0.2*(1.0-maskDark)*mx));
|
||||
float adj = 0.80*maskLight - 0.5*(0.80*maskLight - 1.0)*mx + 0.75*(1.0-mx);
|
||||
mask = maskTmp;
|
||||
pos.x = fract(pos.x/2.0);
|
||||
if (pos.x < 0.5)
|
||||
{ mask.r = adj;
|
||||
mask.b = adj;
|
||||
}
|
||||
else mask.g = adj;
|
||||
}
|
||||
|
||||
// Alternate mask 6
|
||||
else if (shadowMask == 6.0)
|
||||
{
|
||||
float mx = max(max(c.r,c.g),c.b);
|
||||
vec3 maskTmp = vec3( min( 1.33*max(mx-mcut,0.0)/(1.0-mcut) ,maskDark + 0.225*(1.0-maskDark)*mx));
|
||||
float adj = 0.80*maskLight - 0.5*(0.80*maskLight - 1.0)*mx + 0.75*(1.0-mx);
|
||||
mask = maskTmp;
|
||||
pos.x = fract(pos.x/3.0);
|
||||
if (pos.x < 0.333) mask.r = adj;
|
||||
else if (pos.x < 0.666) mask.g = adj;
|
||||
else mask.b = adj;
|
||||
}
|
||||
|
||||
// Alternate mask 7
|
||||
else if (shadowMask == 7.0)
|
||||
{
|
||||
float mx = max(max(c.r,c.g),c.b);
|
||||
float maskTmp = min(1.6*max(mx-mcut,0.0)/(1.0-mcut) ,1.0 + 0.6*(1.0-mx));
|
||||
mask = vec3(maskTmp);
|
||||
pos.x = fract(pos.x/2.0);
|
||||
if (pos.x < 0.5) mask = vec3(1.0 + 0.6*(1.0-mx));
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
float SlotMask(vec2 pos, vec3 c)
|
||||
{
|
||||
if (slotmask == 0.0) return 1.0;
|
||||
|
||||
float mx = pow(max(max(c.r,c.g),c.b),1.33);
|
||||
float mlen = slotwidth*2.0;
|
||||
float px = fract(pos.x/mlen);
|
||||
float py = floor(fract(pos.y/(2.0*double_slot))*2.0*double_slot);
|
||||
float slot_dark = mix(1.0-slotmask, 1.0-0.80*slotmask, mx);
|
||||
float slot = 1.0 + 0.7*slotmask*(1.0-mx);
|
||||
if (py == 0.0 && px < 0.5) slot = slot_dark; else
|
||||
if (py == double_slot && px >= 0.5) slot = slot_dark;
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
// Distortion of scanlines, and end of screen alpha (PD Lottes Curvature)
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
@ -236,26 +310,20 @@ vec2 Overscan(vec2 pos, float dx, float dy){
|
||||
return pos*0.5+0.5;
|
||||
}
|
||||
|
||||
float Overscan2(float pos, float dy){
|
||||
pos=pos*2.0-1.0;
|
||||
pos*=dy;
|
||||
return pos*0.5+0.5;
|
||||
}
|
||||
|
||||
// Borrowed from cgwg's crt-geom, under GPL
|
||||
|
||||
float corner(vec2 coord)
|
||||
{
|
||||
coord *= SourceSize.xy / InputSize.xy;
|
||||
coord = (coord - vec2(0.5)) * 1.0 + vec2(0.5);
|
||||
coord = min(coord, vec2(1.0)-coord) * vec2(1.0, params.OutputSize.y*params.OutputSize.z);
|
||||
vec2 cdist = vec2(max(csize,0.002));
|
||||
coord = min(coord, vec2(1.0)-coord) * vec2(1.0, OutputSize.y/OutputSize.x);
|
||||
vec2 cdist = vec2(max(csize, max((1.0-smoothstep(100.0,600.0,bsize))*0.01,0.002)));
|
||||
coord = (cdist - min(coord,cdist));
|
||||
float dist = sqrt(dot(coord,coord));
|
||||
return clamp((cdist.x-dist)*700.0,0.0, 1.0);
|
||||
return clamp((cdist.x-dist)*bsize,0.0, 1.0);
|
||||
}
|
||||
|
||||
const float sqrt3 = 1.732050807568877;
|
||||
|
||||
vec3 gamma_correct(vec3 color, vec3 tmp)
|
||||
{
|
||||
return color*mix(GTW, 1.0, max(max(tmp.r,tmp.g),tmp.b));
|
||||
@ -263,29 +331,27 @@ vec3 gamma_correct(vec3 color, vec3 tmp)
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 lum = texture(lum_pass, vec2(0.33,0.33)).xyz;
|
||||
float lum = COMPAT_TEXTURE(PassPrev4Texture, vec2(0.33,0.33)).a;
|
||||
|
||||
// Calculating texel coordinates
|
||||
|
||||
vec2 texcoord = vTexCoord.xy;
|
||||
if (IOS == 1.0){
|
||||
vec2 ofactor = params.OutputSize.xy*params.SourceSize.zw;
|
||||
vec2 texcoord = TEX0.xy;
|
||||
if (IOS > 0.0){
|
||||
vec2 ofactor = OutputSize.xy/InputSize.xy;
|
||||
vec2 intfactor = round(ofactor);
|
||||
vec2 diff = ofactor/intfactor;
|
||||
vec2 smartcoord;
|
||||
smartcoord.x = Overscan2(vTexCoord.x, diff.x);
|
||||
smartcoord.y = Overscan2(vTexCoord.y, diff.y);
|
||||
texcoord = (TATE > 0.5) ? vec2(smartcoord.x, texcoord.y) :
|
||||
vec2(texcoord.x, smartcoord.y);
|
||||
float scan = mix(diff.y, diff.x, TATE);
|
||||
texcoord = Overscan(texcoord*(SourceSize.xy/InputSize.xy), scan, scan)*(InputSize.xy/SourceSize.xy);
|
||||
if (IOS == 1.0) texcoord = mix(vec2(TEX0.x, texcoord.y), vec2(texcoord.x, TEX0.y), TATE);
|
||||
}
|
||||
|
||||
float factor = 1.00 + (1.0-0.5*OS)*BLOOM/100.0 - lum.x*BLOOM/100.0;
|
||||
texcoord = Overscan(texcoord, factor, factor);
|
||||
vec2 pos = Warp(texcoord);
|
||||
vec2 pos0 = Warp(vTexCoord.xy);
|
||||
float factor = 1.00 + (1.0-0.5*OS)*BLOOM/100.0 - lum*BLOOM/100.0;
|
||||
texcoord = Overscan(texcoord*(SourceSize.xy/InputSize.xy), factor, factor)*(InputSize.xy/SourceSize.xy);
|
||||
vec2 pos = Warp(texcoord*(TextureSize.xy/InputSize.xy))*(InputSize.xy/TextureSize.xy);
|
||||
vec2 pos0 = Warp(TEX0.xy*(TextureSize.xy/InputSize.xy))*(InputSize.xy/TextureSize.xy);
|
||||
|
||||
vec2 ps = params.SourceSize.zw;
|
||||
vec2 OGL2Pos = pos * params.SourceSize.xy - ((TATE < 0.5) ?
|
||||
vec2 ps = SourceSize.zw;
|
||||
vec2 OGL2Pos = pos * SourceSize.xy - ((TATE < 0.5) ?
|
||||
vec2(0.0,0.5) : vec2(0.5, 0.0));
|
||||
vec2 fp = fract(OGL2Pos);
|
||||
vec2 dx = vec2(ps.x,0.0);
|
||||
@ -311,61 +377,108 @@ void main()
|
||||
|
||||
bool sharp = (s_sharp > 0.0);
|
||||
|
||||
float wl2 = 1.5 + fpx; wl2*=wl2; wl2 = exp2(-h_sharp*wl2); wl2 = max(wl2 - s_sharp, -wl2);
|
||||
float wl1 = 0.5 + fpx; wl1*=wl1; wl1 = exp2(-h_sharp*wl1); wl1 = max(wl1 - s_sharp, -0.4*s_sharp);
|
||||
float wct = 0.5 - fpx; wct*=wct; wct = exp2(-h_sharp*wct); wct = max(wct - s_sharp, s_sharp);
|
||||
float wr1 = 1.5 - fpx; wr1*=wr1; wr1 = exp2(-h_sharp*wr1); wr1 = max(wr1 - s_sharp, -0.4*s_sharp);
|
||||
float wr2 = 2.5 - fpx; wr2*=wr2; wr2 = exp2(-h_sharp*wr2); wr2 = max(wr2 - s_sharp, -wr2);
|
||||
|
||||
float wt = 1.0/(wl2+wl1+wct+wr1+wr2);
|
||||
float hsharp_tl, hsharp_tr, hsharp_bl, hsharp_br, hsharp_tc, hsharp_bc;
|
||||
|
||||
vec3 l2 = texture(linearize_pass, pC4 -off2).xyz;
|
||||
vec3 l1 = texture(linearize_pass, pC4 -offx).xyz;
|
||||
vec3 ct = texture(linearize_pass, pC4 ).xyz;
|
||||
vec3 r1 = texture(linearize_pass, pC4 +offx).xyz;
|
||||
vec3 r2 = texture(linearize_pass, pC4 +off2).xyz;
|
||||
if (h_smart == 0.0)
|
||||
{
|
||||
hsharp_tl = h_sharp; hsharp_tr = h_sharp; hsharp_bl = h_sharp; hsharp_br = h_sharp; hsharp_tc = h_sharp; hsharp_bc = h_sharp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reading differences for smoothing
|
||||
vec3 diffs_top = COMPAT_TEXTURE(PassPrev4Texture, pC4 ).xyz;
|
||||
vec3 diffs_bot = COMPAT_TEXTURE(PassPrev4Texture, pC4 + offy).xyz;
|
||||
|
||||
vec3 color1 = (l2*wl2 + l1*wl1 + ct*wct + r1*wr1 + r2*wr2)*wt;
|
||||
if(TATE > 0.5)
|
||||
{
|
||||
diffs_top.x = floor(10.0*diffs_top.z)*0.11111; diffs_top.y = fract(10.0*diffs_top.z)*1.11111;
|
||||
diffs_bot.x = floor(10.0*diffs_bot.z)*0.11111; diffs_bot.y = fract(10.0*diffs_bot.z)*1.11111;
|
||||
}
|
||||
|
||||
float ls = mix (4.5, 2.25, h_smart);
|
||||
hsharp_tl = mix(h_sharp, ls, diffs_top.x);
|
||||
hsharp_tr = mix(h_sharp, ls, diffs_top.y);
|
||||
hsharp_bl = mix(h_sharp, ls, diffs_bot.x);
|
||||
hsharp_br = mix(h_sharp, ls, diffs_bot.y);
|
||||
hsharp_tc = hsharp_tl;
|
||||
hsharp_bc = hsharp_bl;
|
||||
if (fpx == 0.5) { hsharp_tc = 0.5*(hsharp_tl + hsharp_tr); hsharp_bc = 0.5*(hsharp_bl + hsharp_br); }
|
||||
if (fpx > 0.5) { hsharp_tc = hsharp_tr; hsharp_bc = hsharp_bl; }
|
||||
}
|
||||
|
||||
float wl2 = 1.5 + fpx; wl2*=wl2; float twl2 = exp2(-hsharp_tl*wl2); twl2 = max(twl2 - s_sharp, -twl2); float bwl2 = exp2(-hsharp_bl*wl2); bwl2 = max(bwl2 - s_sharp, -bwl2);
|
||||
float wl1 = 0.5 + fpx; wl1*=wl1; float twl1 = exp2(-hsharp_tl*wl1); twl1 = max(twl1 - s_sharp, -0.4*s_sharp); float bwl1 = exp2(-hsharp_bl*wl1); bwl1 = max(bwl1 - s_sharp, -0.4*s_sharp);
|
||||
float wct = 0.5 - fpx; wct*=wct; float twct = exp2(-hsharp_tc*wct); twct = max(twct - s_sharp, s_sharp); float bwct = exp2(-hsharp_bc*wct); bwct = max(bwct - s_sharp, s_sharp);
|
||||
float wr1 = 1.5 - fpx; wr1*=wr1; float twr1 = exp2(-hsharp_tr*wr1); twr1 = max(twr1 - s_sharp, -0.4*s_sharp); float bwr1 = exp2(-hsharp_br*wr1); bwr1 = max(bwr1 - s_sharp, -0.4*s_sharp);
|
||||
float wr2 = 2.5 - fpx; wr2*=wr2; float twr2 = exp2(-hsharp_tr*wr2); twr2 = max(twr2 - s_sharp, -twr2); float bwr2 = exp2(-hsharp_br*wr2); bwr2 = max(bwr2 - s_sharp, -bwr2);
|
||||
|
||||
float wtt = 1.0/(twl2+twl1+twct+twr1+twr2);
|
||||
float wtb = 1.0/(bwl2+bwl1+bwct+bwr1+bwr2);
|
||||
|
||||
vec3 l2 = COMPAT_TEXTURE(PassPrev3Texture, pC4 -off2).xyz;
|
||||
vec3 l1 = COMPAT_TEXTURE(PassPrev3Texture, pC4 -offx).xyz;
|
||||
vec3 ct = COMPAT_TEXTURE(PassPrev3Texture, pC4 ).xyz;
|
||||
vec3 r1 = COMPAT_TEXTURE(PassPrev3Texture, pC4 +offx).xyz;
|
||||
vec3 r2 = COMPAT_TEXTURE(PassPrev3Texture, pC4 +off2).xyz;
|
||||
|
||||
vec3 color1 = (l2*twl2 + l1*twl1 + ct*twct + r1*twr1 + r2*twr2)*wtt;
|
||||
if (sharp) color1 = clamp(color1, min(min(l1,r1),ct), max(max(l1,r1),ct));
|
||||
|
||||
l2 = texture(linearize_pass, pC4 -off2 +offy).xyz;
|
||||
l1 = texture(linearize_pass, pC4 -offx +offy).xyz;
|
||||
ct = texture(linearize_pass, pC4 +offy).xyz;
|
||||
r1 = texture(linearize_pass, pC4 +offx +offy).xyz;
|
||||
r2 = texture(linearize_pass, pC4 +off2 +offy).xyz;
|
||||
l2 = COMPAT_TEXTURE(PassPrev3Texture, pC4 -off2 +offy).xyz;
|
||||
l1 = COMPAT_TEXTURE(PassPrev3Texture, pC4 -offx +offy).xyz;
|
||||
ct = COMPAT_TEXTURE(PassPrev3Texture, pC4 +offy).xyz;
|
||||
r1 = COMPAT_TEXTURE(PassPrev3Texture, pC4 +offx +offy).xyz;
|
||||
r2 = COMPAT_TEXTURE(PassPrev3Texture, pC4 +off2 +offy).xyz;
|
||||
|
||||
vec3 color2 = (l2*wl2 + l1*wl1 + ct*wct + r1*wr1 + r2*wr2)*wt;
|
||||
vec3 color2 = (l2*bwl2 + l1*bwl1 + ct*bwct + r1*bwr1 + r2*bwr2)*wtb;
|
||||
if (sharp) color2 = clamp(color2, min(min(l1,r1),ct), max(max(l1,r1),ct));
|
||||
|
||||
// calculating scanlines
|
||||
|
||||
float f = (TATE < 0.5) ? fp.y : fp.x;
|
||||
|
||||
vec3 w1 = sw(f,color1);
|
||||
vec3 w2 = sw(1.0-f,color2);
|
||||
float shape1 = mix(scanline1, scanline2, f);
|
||||
float shape2 = mix(scanline1, scanline2, 1.0-f);
|
||||
|
||||
if (gsl == 1.0) { w1 = sw2(1.0-f,color1); w2 = sw2(f,color2);}
|
||||
float wt1 = st(f, shape1);
|
||||
float wt2 = st(1.0-f, shape2);
|
||||
vec3 color0 = color1*wt1 + color2*wt2;
|
||||
vec3 ctmp = color0/(wt1+wt2);
|
||||
vec3 tmp = pow(ctmp, vec3(1.0/gamma_out));
|
||||
|
||||
vec3 w1,w2 = vec3(0.0);
|
||||
|
||||
vec3 cref1 = mix(ctmp, color1, beam_size);
|
||||
vec3 cref2 = mix(ctmp, color2, beam_size);
|
||||
|
||||
vec3 shift = vec3(-vertmask, vertmask, -vertmask);
|
||||
|
||||
vec3 f1 = clamp(vec3(f) + shift*0.5*(1.0+f), 0.0, 1.0);
|
||||
vec3 f2 = clamp(vec3(1.0-f) - shift*0.5*(2.0-f), 0.0, 1.0);
|
||||
|
||||
if (gsl == 0.0) { w1 = sw0(f1,cref1,shape1); w2 = sw0(f2,cref2,shape2);} else
|
||||
if (gsl == 1.0) { w1 = sw1(f1,cref1,shape1); w2 = sw1(f2,cref2,shape2);} else
|
||||
if (gsl == 2.0) { w1 = sw2(f1,cref1,shape1); w2 = sw2(f2,cref2,shape2);}
|
||||
|
||||
vec3 color = color1*w1 + color2*w2;
|
||||
vec3 ctmp = color/(w1+w2);
|
||||
|
||||
color = pow(color, vec3(1.0/gamma_out));
|
||||
float l = length(color);
|
||||
color = normalize(pow(color + vec3(eps), vec3(saturation,saturation,saturation)))*l;
|
||||
color*=brightboost;
|
||||
color = gamma_correct(color,ctmp);
|
||||
color = pow(color, vec3(gamma_out));
|
||||
color = min(color, 1.0);
|
||||
|
||||
// Apply Mask
|
||||
|
||||
color *= (TATE < 0.5) ? Mask(gl_FragCoord.xy * 1.000001) :
|
||||
Mask(gl_FragCoord.yx * 1.000001);
|
||||
color *= (TATE < 0.5) ? Mask(gl_FragCoord.xy * 1.000001,tmp) :
|
||||
Mask(gl_FragCoord.yx * 1.000001,tmp);
|
||||
|
||||
vec3 Bloom = texture(Source, pos).xyz;
|
||||
color = min(color,1.0);
|
||||
|
||||
color *= (TATE < 0.5) ? SlotMask(gl_FragCoord.xy * 1.000001,tmp) :
|
||||
SlotMask(gl_FragCoord.yx * 1.000001,tmp);
|
||||
|
||||
vec3 Bloom = COMPAT_TEXTURE(Texture, pos).xyz;
|
||||
|
||||
color+=glow*Bloom;
|
||||
color = min(color, 1.0);
|
||||
|
||||
color = pow(color, vec3(1.0/gamma_out));
|
||||
FragColor = vec4(color*corner(pos0), 1.0);
|
||||
|
@ -9,7 +9,12 @@ layout(push_constant) uniform Push
|
||||
float WP;
|
||||
} params;
|
||||
|
||||
#pragma parameter WP "D65 to D50 strength %" 0.0 -100.0 100.0 5.0
|
||||
#pragma parameter WP "Color Temperature %" 0.0 -100.0 100.0 5.0
|
||||
|
||||
#define WP params.WP
|
||||
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define TEX0 vTexCoord
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
@ -32,26 +37,46 @@ layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
const mat3 D65 = mat3 (
|
||||
0.5767309, 0.2973769, 0.0270343,
|
||||
0.1855540, 0.6273491, 0.0706872,
|
||||
0.1881852, 0.0752741, 0.9911085);
|
||||
const mat3 D65_to_XYZ = mat3 (
|
||||
0.4306190, 0.2220379, 0.0201853,
|
||||
0.3415419, 0.7066384, 0.1295504,
|
||||
0.1783091, 0.0713236, 0.9390944);
|
||||
|
||||
const mat3 D50 = mat3 (
|
||||
1.7552599, -0.5441336, 0.0063467,
|
||||
-0.4836786, 1.5068789, -0.0175761,
|
||||
-0.2530000, 0.0215528, 1.2256959);
|
||||
const mat3 XYZ_to_D65 = mat3 (
|
||||
3.0628971, -0.9692660, 0.0678775,
|
||||
-1.3931791, 1.8760108, -0.2288548,
|
||||
-0.4757517, 0.0415560, 1.0693490);
|
||||
|
||||
const mat3 D50_to_XYZ = mat3 (
|
||||
0.4552773, 0.2323025, 0.0145457,
|
||||
0.3675500, 0.7077956, 0.1049154,
|
||||
0.1413926, 0.0599019, 0.7057489);
|
||||
|
||||
const mat3 XYZ_to_D50 = mat3 (
|
||||
2.9603944, -0.9787684, 0.0844874,
|
||||
-1.4678519, 1.9161415, -0.2545973,
|
||||
-0.4685105, 0.0334540, 1.4216174);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 color = texture(Source, vTexCoord.xy).rgb;
|
||||
vec3 color = COMPAT_TEXTURE(Source, TEX0.xy).rgb;
|
||||
float p = 2.4;
|
||||
|
||||
vec3 c65 = D65*color;
|
||||
vec3 c50 = D50*c65;
|
||||
color = pow(color, vec3(p));
|
||||
|
||||
float m = params.WP/100.0;
|
||||
vec3 warmer = D50_to_XYZ*color;
|
||||
warmer = XYZ_to_D65*warmer;
|
||||
|
||||
color = (1.0-m)*color + m*c50;
|
||||
vec3 cooler = D65_to_XYZ*color;
|
||||
cooler = XYZ_to_D50*cooler;
|
||||
|
||||
float m = abs(WP)/100.0;
|
||||
|
||||
vec3 comp = (WP < 0.0) ? cooler : warmer;
|
||||
|
||||
color = mix(color, comp, m);
|
||||
|
||||
color = pow(color, vec3(1.0/p));
|
||||
|
||||
FragColor = vec4(color,1.0);
|
||||
}
|
126
crt/shaders/guest/fast/crt-guest-dr-venom-pass1.slang
Normal file
126
crt/shaders/guest/fast/crt-guest-dr-venom-pass1.slang
Normal file
@ -0,0 +1,126 @@
|
||||
#version 450
|
||||
|
||||
/*
|
||||
CRT - Guest - Dr. Venom - Pass1
|
||||
|
||||
Copyright (C) 2018-2019 guest(r) - guest.r@gmail.com
|
||||
|
||||
Incorporates many good ideas and suggestions from Dr. Venom.
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float h_sharp;
|
||||
float s_sharp;
|
||||
float h_smart;
|
||||
} params;
|
||||
|
||||
#pragma parameter h_sharp "Horizontal sharpness" 5.00 1.5 20.0 0.25
|
||||
#define h_sharp params.h_sharp
|
||||
#pragma parameter s_sharp "Substractive sharpness" 0.05 0.0 0.20 0.01
|
||||
#define s_sharp params.s_sharp
|
||||
#pragma parameter h_smart "Smart Horizontal Smoothing" 0.0 0.0 1.0 0.1
|
||||
#define h_smart params.h_smart
|
||||
#define SourceSize params.SourceSize
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
} global;
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord * 1.00001;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
layout(set = 0, binding = 3) uniform sampler2D SmoothPass;
|
||||
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define PassPrev2Texture SmoothPass
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 ps = SourceSize.zw;
|
||||
vec2 OGL2Pos = vTexCoord * SourceSize.xy;
|
||||
vec2 fp = fract(OGL2Pos);
|
||||
vec2 dx = vec2(ps.x,0.0);
|
||||
vec2 dy = vec2(0.0, ps.y);
|
||||
vec2 pC4 = floor(OGL2Pos) * ps + 0.5*ps;
|
||||
|
||||
// Reading the texels
|
||||
vec2 x2 = 2.0*dx;
|
||||
vec2 y2 = 2.0*dy;
|
||||
|
||||
bool sharp = (s_sharp > 0.0);
|
||||
|
||||
float hsharp_tl, hsharp_tr, hsharp_tc; float s_sharpl = s_sharp; float s_sharpr = s_sharp; float s_sharpc = s_sharp;
|
||||
|
||||
if (h_smart == 0.0)
|
||||
{
|
||||
hsharp_tl = h_sharp; hsharp_tr = h_sharp; hsharp_tc = h_sharp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reading differences for smoothing
|
||||
vec2 diffs = COMPAT_TEXTURE(PassPrev2Texture, pC4).xy;
|
||||
|
||||
float ls = mix (4.25, 2.25, h_smart);
|
||||
hsharp_tl = mix(h_sharp, ls, diffs.x);
|
||||
hsharp_tr = mix(h_sharp, ls, diffs.y);
|
||||
|
||||
s_sharpl = mix(s_sharp, 0.0, diffs.x);
|
||||
s_sharpr = mix(s_sharp, 0.0, diffs.y);
|
||||
|
||||
hsharp_tc = hsharp_tl;
|
||||
if (fp.x == 0.5) { hsharp_tc = 0.5*(hsharp_tl + hsharp_tr); s_sharpc = 0.5*(s_sharpl + s_sharpr); }
|
||||
if (fp.x > 0.5) { hsharp_tc = hsharp_tr; }
|
||||
}
|
||||
|
||||
float wl2 = 1.5 + fp.x; wl2*=wl2; float twl2 = exp2(-hsharp_tl*wl2); twl2 = max(twl2 - s_sharpl, -twl2);
|
||||
float wl1 = 0.5 + fp.x; wl1*=wl1; float twl1 = exp2(-hsharp_tl*wl1); twl1 = max(twl1 - s_sharpl, -0.4*s_sharpl);
|
||||
float wct = 0.5 - fp.x; wct*=wct; float twct = exp2(-hsharp_tc*wct); twct = max(twct - s_sharpc, s_sharpc);
|
||||
float wr1 = 1.5 - fp.x; wr1*=wr1; float twr1 = exp2(-hsharp_tr*wr1); twr1 = max(twr1 - s_sharpr, -0.4*s_sharpr);
|
||||
float wr2 = 2.5 - fp.x; wr2*=wr2; float twr2 = exp2(-hsharp_tr*wr2); twr2 = max(twr2 - s_sharpr, -twr2);
|
||||
|
||||
float wtt = 1.0/(twl2+twl1+twct+twr1+twr2);
|
||||
|
||||
vec3 l2 = COMPAT_TEXTURE(Source, pC4 -x2).xyz;
|
||||
vec3 l1 = COMPAT_TEXTURE(Source, pC4 -dx).xyz;
|
||||
vec3 ct = COMPAT_TEXTURE(Source, pC4 ).xyz;
|
||||
vec3 r1 = COMPAT_TEXTURE(Source, pC4 +dx).xyz;
|
||||
vec3 r2 = COMPAT_TEXTURE(Source, pC4 +x2).xyz;
|
||||
|
||||
vec3 color = (l2*twl2 + l1*twl1 + ct*twct + r1*twr1 + r2*twr2)*wtt;
|
||||
if (sharp) color = clamp(color, 0.8*min(min(l1,r1),ct), 1.2*max(max(l1,r1),ct));
|
||||
|
||||
FragColor = vec4(color, 1.0);
|
||||
}
|
328
crt/shaders/guest/fast/crt-guest-dr-venom-pass2.slang
Normal file
328
crt/shaders/guest/fast/crt-guest-dr-venom-pass2.slang
Normal file
@ -0,0 +1,328 @@
|
||||
#version 450
|
||||
|
||||
/*
|
||||
CRT - Guest - Dr. Venom - Pass2
|
||||
|
||||
Copyright (C) 2018-2019 guest(r) - guest.r@gmail.com
|
||||
|
||||
Incorporates many good ideas and suggestions from Dr. Venom.
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
float brightboost, IOS, gsl, scanline1, scanline2, beam_min, beam_max, s_power, beam_size, shadowMask,
|
||||
masksize, vertmask, slotmask, slotwidth, double_slot, mcut, maskDark, maskLight, CGWG, gamma_out;
|
||||
} params;
|
||||
|
||||
#pragma parameter brightboost "Bright boost" 1.30 0.50 2.00 0.01
|
||||
#define brightboost params.brightboost // adjust brightness
|
||||
#pragma parameter IOS "Smart Y Integer Scaling" 0.0 0.0 1.0 1.0
|
||||
#define IOS params.IOS // smart integer scaling
|
||||
#pragma parameter gsl "Scanline Type" 1.0 0.0 2.0 1.0
|
||||
#define gsl params.gsl // Alternate scanlines
|
||||
#pragma parameter scanline1 "Scanline beam shape low" 8.0 1.0 15.0 1.0
|
||||
#define scanline1 params.scanline1 // scanline param, vertical sharpness
|
||||
#pragma parameter scanline2 "Scanline beam shape high" 8.0 5.0 23.0 1.0
|
||||
#define scanline2 params.scanline2 // scanline param, vertical sharpness
|
||||
#pragma parameter beam_min "Scanline dark" 1.25 0.5 2.0 0.05
|
||||
#define beam_min params.beam_min // dark area beam min - narrow
|
||||
#pragma parameter beam_max "Scanline bright" 1.05 0.5 2.0 0.05
|
||||
#define beam_max params.beam_max // bright area beam max - wide
|
||||
#pragma parameter s_power "Scanline intensity" 1.0 0.5 2.5 0.05
|
||||
#define s_power params.s_power // scanline intensity
|
||||
#pragma parameter beam_size "Increased bright scanline beam" 0.65 0.0 1.0 0.05
|
||||
#define beam_size params.beam_size // increased max. beam size
|
||||
#pragma parameter shadowMask "CRT Mask: 0:CGWG, 1-4:Lottes, 5-6:'Trinitron'" 5.0 -1.0 6.0 1.0
|
||||
#define shadowMask params.shadowMask // Mask Style
|
||||
#pragma parameter masksize "CRT Mask Size (2.0 is nice in 4k)" 1.0 1.0 2.0 1.0
|
||||
#define masksize params.masksize // Mask Size
|
||||
#pragma parameter vertmask "PVM Like Colors" 0.05 0.0 0.25 0.01
|
||||
#define vertmask params.vertmask // Vertical mask
|
||||
#pragma parameter slotmask "Slot Mask Strength" 0.0 0.0 1.0 0.05
|
||||
#define slotmask params.slotmask // Slot Mask ON/OFF
|
||||
#pragma parameter slotwidth "Slot Mask Width" 2.0 2.0 6.0 0.5
|
||||
#define slotwidth params.slotwidth // Slot Mask Width
|
||||
#pragma parameter double_slot "Slot Mask Height: 2x1 or 4x1" 1.0 1.0 2.0 1.0
|
||||
#define double_slot params.double_slot // Slot Mask Height
|
||||
#pragma parameter mcut "Mask 5&6 cutoff" 0.2 0.0 0.5 0.05
|
||||
#define mcut params.mcut // Mask 5&6 cutoff
|
||||
#pragma parameter maskDark "Mask Dark" 0.5 0.0 2.0 0.05
|
||||
#define maskDark params.maskDark // Dark "Phosphor"
|
||||
#pragma parameter maskLight "Mask Light" 1.5 0.0 2.0 0.05
|
||||
#define maskLight params.maskLight // Light "Phosphor"
|
||||
#pragma parameter CGWG "CGWG Mask Str." 0.3 0.0 1.0 0.05
|
||||
#define CGWG params.CGWG // CGWG Mask Strength
|
||||
#pragma parameter gamma_out "Gamma out" 2.4 1.0 3.5 0.05
|
||||
#define gamma_out params.gamma_out // output gamma
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
} global;
|
||||
|
||||
#define SourceSize global.SourceSize
|
||||
#define OutputSize global.OutputSize
|
||||
#define FrameCount global.FrameCount
|
||||
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
#define gl_FragCoord (vTexCoord.xy * OutputSize.xy)
|
||||
#define InputSize SourceSize
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord * 1.00001;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
#define eps 1e-10
|
||||
|
||||
float st(float x, float scanline)
|
||||
{
|
||||
return exp2(-scanline*x*x);
|
||||
}
|
||||
|
||||
vec3 sw0(vec3 x, vec3 color, float scanline)
|
||||
{
|
||||
vec3 tmp = mix(vec3(beam_min),vec3(beam_max), color);
|
||||
vec3 ex = x*tmp;
|
||||
return exp2(-scanline*ex*ex);
|
||||
}
|
||||
|
||||
vec3 sw1(vec3 x, vec3 color, float scanline)
|
||||
{
|
||||
float mx = max(max(color.r, color.g),color.b);
|
||||
x = mix (x, beam_min*x, max(x-0.4*mx,0.0));
|
||||
vec3 tmp = mix(vec3(1.2*beam_min),vec3(beam_max), color);
|
||||
vec3 ex = x*tmp;
|
||||
float br = clamp(0.8*beam_min - 1.0, 0.2, 0.45);
|
||||
return exp2(-scanline*ex*ex)/(1.0-br+br*color);
|
||||
}
|
||||
|
||||
vec3 sw2(vec3 x, vec3 color, float scanline)
|
||||
{
|
||||
vec3 tmp = mix(vec3(2.75*beam_min),vec3(beam_max), color);
|
||||
tmp = mix(vec3(beam_max), tmp, pow(x, vec3(max(max(color.r, color.g),color.b)+0.3)));
|
||||
vec3 ex = x*tmp;
|
||||
return exp2(-scanline*ex*ex)/(0.6 + 0.4*color);
|
||||
}
|
||||
|
||||
// Shadow mask (1-4 from PD CRT Lottes shader).
|
||||
vec3 Mask(vec2 pos, vec3 c)
|
||||
{
|
||||
pos = floor(pos/masksize);
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
|
||||
|
||||
// No mask
|
||||
if (shadowMask == -1.0)
|
||||
{
|
||||
mask = vec3(1.0);
|
||||
}
|
||||
|
||||
// Phosphor.
|
||||
else if (shadowMask == 0.0)
|
||||
{
|
||||
pos.x = fract(pos.x*0.5);
|
||||
float mc = 1.0 - CGWG;
|
||||
if (pos.x < 0.5) { mask.r = 1.1; mask.g = mc; mask.b = 1.1; }
|
||||
else { mask.r = mc; mask.g = 1.1; mask.b = mc; }
|
||||
}
|
||||
|
||||
// Very compressed TV style shadow mask.
|
||||
else if (shadowMask == 1.0)
|
||||
{
|
||||
float line = maskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x/6.0) < 0.5)
|
||||
odd = 1.0;
|
||||
if (fract((pos.y + odd)/2.0) < 0.5)
|
||||
line = maskDark;
|
||||
|
||||
pos.x = fract(pos.x/3.0);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
|
||||
mask*=line;
|
||||
}
|
||||
|
||||
// Aperture-grille.
|
||||
else if (shadowMask == 2.0)
|
||||
{
|
||||
pos.x = fract(pos.x/3.0);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
else if (shadowMask == 3.0)
|
||||
{
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x/6.0);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// VGA style shadow mask.
|
||||
else if (shadowMask == 4.0)
|
||||
{
|
||||
pos.xy = floor(pos.xy*vec2(1.0, 0.5));
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x/6.0);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// Alternate mask 5
|
||||
else if (shadowMask == 5.0)
|
||||
{
|
||||
float mx = max(max(c.r,c.g),c.b);
|
||||
vec3 maskTmp = vec3( min( 1.25*max(mx-mcut,0.0)/(1.0-mcut) ,maskDark + 0.2*(1.0-maskDark)*mx));
|
||||
float adj = 0.80*maskLight - 0.5*(0.80*maskLight - 1.0)*mx + 0.75*(1.0-mx);
|
||||
mask = maskTmp;
|
||||
pos.x = fract(pos.x/2.0);
|
||||
if (pos.x < 0.5)
|
||||
{ mask.r = adj;
|
||||
mask.b = adj;
|
||||
}
|
||||
else mask.g = adj;
|
||||
}
|
||||
|
||||
// Alternate mask 6
|
||||
else if (shadowMask == 6.0)
|
||||
{
|
||||
float mx = max(max(c.r,c.g),c.b);
|
||||
vec3 maskTmp = vec3( min( 1.5*max(mx-mcut,0.0)/(1.0-mcut) ,maskDark + 0.225*(1.0-maskDark)*mx));
|
||||
float adj = 0.80*maskLight - 0.5*(0.80*maskLight - 1.0)*mx + 0.75*(1.0-mx);
|
||||
mask = maskTmp;
|
||||
pos.x = fract(pos.x/3.0);
|
||||
if (pos.x < 0.333) mask.r = adj;
|
||||
else if (pos.x < 0.666) mask.g = adj;
|
||||
else mask.b = adj;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
float SlotMask(vec2 pos, vec3 c)
|
||||
{
|
||||
if (slotmask == 0.0) return 1.0;
|
||||
|
||||
float mx = pow(max(max(c.r,c.g),c.b),1.33);
|
||||
float mlen = slotwidth*2.0;
|
||||
float px = fract(pos.x/mlen);
|
||||
float py = floor(fract(pos.y/(2.0*double_slot))*2.0*double_slot);
|
||||
float slot_dark = mix(1.0-slotmask, 1.0-0.80*slotmask, mx);
|
||||
float slot = 1.0 + 0.7*slotmask*(1.0-mx);
|
||||
if (py == 0.0 && px < 0.5) slot = slot_dark; else
|
||||
if (py == double_slot && px >= 0.5) slot = slot_dark;
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
float Overscan2(float pos, float dy){
|
||||
pos=pos*2.0-1.0;
|
||||
pos*=dy;
|
||||
return pos*0.5+0.5;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texcoord = vTexCoord;
|
||||
|
||||
if (IOS == 1.0){
|
||||
float ofactor = OutputSize.y/InputSize.y;
|
||||
float intfactor = round(ofactor);
|
||||
float diff = ofactor/intfactor;
|
||||
texcoord.y = Overscan2(texcoord.y*(SourceSize.y/InputSize.y), diff)*(InputSize.y/SourceSize.y);
|
||||
}
|
||||
|
||||
vec2 ps = SourceSize.zw;
|
||||
vec2 OGL2Pos = texcoord * SourceSize.xy - vec2(0.0,0.5);
|
||||
vec2 fp = fract(OGL2Pos);
|
||||
vec2 dx = vec2(ps.x,0.0);
|
||||
vec2 dy = vec2(0.0, ps.y);
|
||||
|
||||
vec2 pC4 = floor(OGL2Pos) * ps + 0.5*ps;
|
||||
|
||||
vec3 color1 = COMPAT_TEXTURE(Source, pC4 ).xyz;
|
||||
vec3 color2 = COMPAT_TEXTURE(Source, pC4 +dy).xyz;
|
||||
|
||||
// calculating scanlines
|
||||
|
||||
float f = fp.y;
|
||||
float shape1 = mix(scanline1, scanline2, f);
|
||||
float shape2 = mix(scanline1, scanline2, 1.0-f);
|
||||
|
||||
float wt1 = st(f, shape1);
|
||||
float wt2 = st(1.0-f, shape2);
|
||||
vec3 color0 = color1*wt1 + color2*wt2;
|
||||
vec3 ctmp = color0/(wt1+wt2);
|
||||
vec3 tmp = pow(ctmp, vec3(1.0/gamma_out));
|
||||
|
||||
vec3 w1,w2 = vec3(0.0);
|
||||
|
||||
vec3 cref1 = mix(ctmp, color1, beam_size);
|
||||
vec3 cref2 = mix(ctmp, color2, beam_size);
|
||||
|
||||
vec3 shift = vec3(-vertmask, vertmask, -vertmask);
|
||||
|
||||
vec3 f1 = clamp(vec3(f) + shift*0.5*(1.0+f), 0.0, 1.0);
|
||||
vec3 f2 = clamp(vec3(1.0-f) - shift*0.5*(2.0-f), 0.0, 1.0);
|
||||
|
||||
if (gsl == 0.0) { w1 = sw0(f1,cref1,shape1); w2 = sw0(f2,cref2,shape2);} else
|
||||
if (gsl == 1.0) { w1 = sw1(f1,cref1,shape1); w2 = sw1(f2,cref2,shape2);} else
|
||||
if (gsl == 2.0) { w1 = sw2(f1,cref1,shape1); w2 = sw2(f2,cref2,shape2);}
|
||||
|
||||
vec3 color = color1*pow(w1, vec3(s_power)) + color2*pow(w2, vec3(s_power));
|
||||
|
||||
color*=brightboost;
|
||||
color = min(color, 1.0);
|
||||
|
||||
// Apply Mask
|
||||
|
||||
color *= Mask(gl_FragCoord.xy * 1.000001,tmp);
|
||||
|
||||
color = min(color,1.0);
|
||||
|
||||
color *= SlotMask(gl_FragCoord.xy * 1.000001,tmp);
|
||||
|
||||
color = pow(color, vec3(1.0/gamma_out));
|
||||
FragColor = vec4(color, 1.0);
|
||||
}
|
39
crt/shaders/guest/fast/linearize-multipass.slang
Normal file
39
crt/shaders/guest/fast/linearize-multipass.slang
Normal file
@ -0,0 +1,39 @@
|
||||
#version 450
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float GAMMA_INPUT;
|
||||
} params;
|
||||
|
||||
#pragma parameter GAMMA_INPUT "Gamma Input" 2.4 0.1 5.0 0.05
|
||||
#define GAMMA_INPUT params.GAMMA_INPUT
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
} global;
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Original;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = pow(texture(Original, vTexCoord), vec4(GAMMA_INPUT));
|
||||
}
|
84
crt/shaders/guest/fast/smoothing.slang
Normal file
84
crt/shaders/guest/fast/smoothing.slang
Normal file
@ -0,0 +1,84 @@
|
||||
#version 450
|
||||
|
||||
/*
|
||||
Smart Smoothing Difference Shader
|
||||
|
||||
Copyright (C) 2019 guest(r) - guest.r@gmail.com
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#pragma name SmoothPass
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float STH;
|
||||
} params;
|
||||
|
||||
#pragma parameter STH "Smart Smoothing Threshold" 0.7 0.4 1.2 0.05
|
||||
#define STH params.STH
|
||||
#define SourceSize params.SourceSize
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
} global;
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
float df (vec3 A, vec3 B)
|
||||
{
|
||||
float diff = length(A-B);
|
||||
float luma = clamp(length(0.5*min(A,B) + 0.25*(A+B) + 1e-8), 0.0001, 1.0);
|
||||
float diff1 = diff/luma;
|
||||
return 1.0 - clamp(7.0*(max(1.5*diff,diff1)-STH), 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 dx = vec2(SourceSize.z, 0.0);
|
||||
vec2 dy = vec2(0.0, SourceSize.w);
|
||||
|
||||
vec3 l1 = COMPAT_TEXTURE(Source, vTexCoord.xy -dx).xyz;
|
||||
vec3 ct = COMPAT_TEXTURE(Source, vTexCoord.xy ).xyz;
|
||||
vec3 r1 = COMPAT_TEXTURE(Source, vTexCoord.xy +dx).xyz;
|
||||
|
||||
float dl = df(ct, l1);
|
||||
float dr = df(ct, r1);
|
||||
|
||||
float resx = dl; float resy = dr;
|
||||
|
||||
FragColor = vec4(resx,resy,1.0,1.0);
|
||||
}
|
@ -2,14 +2,11 @@
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float GAMMA_INPUT;
|
||||
} params;
|
||||
|
||||
#pragma parameter GAMMA_INPUT "Gamma Input" 2.4 0.1 5.0 0.05
|
||||
#define GAMMA_INPUT params.GAMMA_INPUT
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
@ -30,9 +27,12 @@ void main()
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D temp_pass;
|
||||
layout(set = 0, binding = 2) uniform sampler2D AfterglowPass;
|
||||
|
||||
#define PassPrev3Texture AfterglowPass
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = pow(vec4(texture(temp_pass, vTexCoord)), vec4(params.GAMMA_INPUT));
|
||||
FragColor = pow(vec4(COMPAT_TEXTURE(PassPrev3Texture, vTexCoord)), vec4(GAMMA_INPUT));
|
||||
}
|
1
crt/shaders/guest/lut/README
Normal file
1
crt/shaders/guest/lut/README
Normal file
@ -0,0 +1 @@
|
||||
LUT's kindly provided by torridgristle.
|
104
crt/shaders/guest/lut/lut.slang
Normal file
104
crt/shaders/guest/lut/lut.slang
Normal file
@ -0,0 +1,104 @@
|
||||
#version 450
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float TNTC;
|
||||
} params;
|
||||
|
||||
#pragma parameter TNTC "LUT Colors" 0.0 0.0 3.0 1.0
|
||||
#define TNTC params.TNTC
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
} global;
|
||||
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
layout(set = 0, binding = 3) uniform sampler2D SamplerLUT1;
|
||||
layout(set = 0, binding = 4) uniform sampler2D SamplerLUT2;
|
||||
layout(set = 0, binding = 5) uniform sampler2D SamplerLUT3;
|
||||
|
||||
#define LUT_Size 32.0
|
||||
#define COMPAT_TEXTURE(c,d) texture(c,d)
|
||||
|
||||
const mat3 D65_to_XYZ = mat3 (
|
||||
0.4306190, 0.2220379, 0.0201853,
|
||||
0.3415419, 0.7066384, 0.1295504,
|
||||
0.1783091, 0.0713236, 0.9390944);
|
||||
|
||||
const mat3 XYZ_to_D50 = mat3 (
|
||||
2.9603944, -0.9787684, 0.0844874,
|
||||
-1.4678519, 1.9161415, -0.2545973,
|
||||
-0.4685105, 0.0334540, 1.4216174);
|
||||
|
||||
|
||||
// This shouldn't be necessary but it seems some undefined values can
|
||||
// creep in and each GPU vendor handles that differently. This keeps
|
||||
// all values within a safe range
|
||||
vec4 mixfix(vec4 a, vec4 b, float c)
|
||||
{
|
||||
return (a.z < 1.0) ? mix(a, b, c) : a;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 imgColor = COMPAT_TEXTURE(Source, vTexCoord.xy);
|
||||
float red = ( imgColor.r * (LUT_Size - 1.0) + 0.499999 ) / (LUT_Size * LUT_Size);
|
||||
float green = ( imgColor.g * (LUT_Size - 1.0) + 0.499999 ) / LUT_Size;
|
||||
float blue1 = (floor( imgColor.b * (LUT_Size - 1.0) ) / LUT_Size) + red;
|
||||
float blue2 = (ceil( imgColor.b * (LUT_Size - 1.0) ) / LUT_Size) + red;
|
||||
float mixer = clamp(max((imgColor.b - blue1) / (blue2 - blue1), 0.0), 0.0, 32.0);
|
||||
vec4 color1, color2, res;
|
||||
if (int(TNTC) == 1)
|
||||
{
|
||||
color1 = COMPAT_TEXTURE( SamplerLUT1, vec2( blue1, green ));
|
||||
color2 = COMPAT_TEXTURE( SamplerLUT1, vec2( blue2, green ));
|
||||
res = mixfix(color1, color2, mixer);
|
||||
float mx = max(res.r,max(res.g,res.b));
|
||||
float l = mix(length(imgColor.rgb), length(res.rgb), max(mx-0.5,0.0));
|
||||
res.rgb = mix(imgColor.rgb, res.rgb, clamp(25.0*(mx-0.02),0.0,1.0));
|
||||
res.rgb = normalize(res.rgb+1e-10)*l;
|
||||
vec3 cooler = D65_to_XYZ*res.rgb;
|
||||
cooler = XYZ_to_D50*cooler;
|
||||
res.rgb = mix(res.rgb, cooler, 0.25);
|
||||
}
|
||||
else if (int(TNTC) == 2)
|
||||
{
|
||||
color1 = COMPAT_TEXTURE( SamplerLUT2, vec2( blue1, green ));
|
||||
color2 = COMPAT_TEXTURE( SamplerLUT2, vec2( blue2, green ));
|
||||
res = mixfix(color1, color2, mixer);
|
||||
float l = mix(length(imgColor.rgb), length(res.rgb), 0.4);
|
||||
res.rgb = normalize(res.rgb + 1e-10)*l;
|
||||
}
|
||||
else if (int(TNTC) == 3)
|
||||
{
|
||||
color1 = COMPAT_TEXTURE( SamplerLUT3, vec2( blue1, green ));
|
||||
color2 = COMPAT_TEXTURE( SamplerLUT3, vec2( blue2, green ));
|
||||
res = mixfix(color1, color2, mixer);
|
||||
res.rgb = pow(res.rgb, vec3(1.0/1.20));
|
||||
float mx = max(res.r,max(res.g,res.b));
|
||||
res.rgb = mix(imgColor.rgb, res.rgb, clamp(25.0*(mx-0.05),0.0,1.0));
|
||||
float l = length(imgColor.rgb);
|
||||
res.rgb = normalize(res.rgb + 1e-10)*l;
|
||||
}
|
||||
|
||||
FragColor = vec4(mix(imgColor.rgb, res.rgb, min(TNTC,1.0)),1.0);
|
||||
}
|
BIN
crt/shaders/guest/lut/other1.png
Normal file
BIN
crt/shaders/guest/lut/other1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
crt/shaders/guest/lut/sony_trinitron1.png
Normal file
BIN
crt/shaders/guest/lut/sony_trinitron1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
BIN
crt/shaders/guest/lut/sony_trinitron2.png
Normal file
BIN
crt/shaders/guest/lut/sony_trinitron2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
80
presets/crt-guest-dr-venom-ntsc-composite.slangp
Normal file
80
presets/crt-guest-dr-venom-ntsc-composite.slangp
Normal file
@ -0,0 +1,80 @@
|
||||
shaders = 11
|
||||
|
||||
shader0 = ../ntsc/shaders/ntsc-pass1-composite-2phase.slang
|
||||
shader1 = ../ntsc/shaders/ntsc-pass2-2phase-gamma.slang
|
||||
|
||||
filter_linear0 = false
|
||||
filter_linear1 = false
|
||||
|
||||
scale_type_x0 = source
|
||||
scale_type_y0 = source
|
||||
scale_x0 = 4.0
|
||||
scale_y0 = 1.0
|
||||
frame_count_mod0 = 2
|
||||
float_framebuffer0 = true
|
||||
|
||||
scale_type1 = source
|
||||
scale_x1 = 0.5
|
||||
scale_y1 = 1.0
|
||||
|
||||
shader2 = ../crt/shaders/guest/lut/lut.slang
|
||||
filter_linear2 = false
|
||||
scale_type2 = source
|
||||
scale2 = 1.0
|
||||
|
||||
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3"
|
||||
SamplerLUT1 = ../crt/shaders/guest/lut/sony_trinitron1.png
|
||||
SamplerLUT1_linear = true
|
||||
SamplerLUT2 = ../crt/shaders/guest/lut/sony_trinitron2.png
|
||||
SamplerLUT2_linear = true
|
||||
SamplerLUT3 = ../crt/shaders/guest/lut/other1.png
|
||||
SamplerLUT3_linear = true
|
||||
|
||||
shader3 = ../crt/shaders/guest/d65-d50.slang
|
||||
filter_linear3 = false
|
||||
scale_type3 = source
|
||||
scale3 = 1.0
|
||||
alias3 = WhitePointPass
|
||||
|
||||
shader4 = ../crt/shaders/guest/afterglow.slang
|
||||
filter_linear4 = false
|
||||
scale_type4 = source
|
||||
scale4 = 1.0
|
||||
alias4 = AfterglowPass
|
||||
|
||||
shader5 = ../crt/shaders/guest/avg-lum0.slang
|
||||
filter_linear5 = false
|
||||
scale_type5 = source
|
||||
scale5 = 1.0
|
||||
|
||||
shader6 = ../crt/shaders/guest/avg-lum.slang
|
||||
filter_linear6 = false
|
||||
scale_type6 = source
|
||||
scale6 = 1.0
|
||||
mipmap_input6 = true
|
||||
alias6 = AvgLumPass
|
||||
|
||||
shader7 = ../crt/shaders/guest/linearize.slang
|
||||
filter_linear7 = false
|
||||
scale_type7 = source
|
||||
scale7 = 1.0
|
||||
float_framebuffer7 = true
|
||||
alias7 = LinearizePass
|
||||
|
||||
shader8 = ../crt/shaders/guest/blur_horiz.slang
|
||||
filter_linear8 = false
|
||||
scale_type8 = source
|
||||
scale8 = 1.0
|
||||
float_framebuffer8 = true
|
||||
|
||||
shader9 = ../crt/shaders/guest/blur_vert.slang
|
||||
filter_linear9 = false
|
||||
scale_type9 = source
|
||||
scale9 = 1.0
|
||||
float_framebuffer9 = true
|
||||
|
||||
shader10 = ../crt/shaders/guest/crt-guest-dr-venom.slang
|
||||
filter_linear10 = true
|
||||
scale_type10 = viewport
|
||||
scale_x10 = 1.0
|
||||
scale_y10 = 1.0
|
Loading…
Reference in New Issue
Block a user