[HLSL CODE] Effect: Color Filter - Channel Isolation - v1.4

share shaders here
  • Author
  • Message
Offline
*sensei*
Posts: 372
Joined: 28 Jul 2013, 23:26

[HLSL CODE] Effect: Color Filter - Channel Isolation - v1.4

Hi all,
A while ago I asked for some examples of the effect, while I was pointed to some online articles, the results were really underwhelming. I have since constructed my own effect which at least reacts as it should and is fully configurable.

What this effect does:
It can isolate certain colors (hue's) and desaturate everything around it (scroll down for a screenshot). You can create SinCity like looks or, for example only leave the red channel open instead. You can select this in the GUI and set the range to which the effect should take place around that hue (including surrounding hue's, or not). You can use this effect for various other purposes related to color when you combine it, be creative, it's pretty powerful.

Hue color goes like this where the left represents the value 0.0 and right 1.0. The GUI element to set this is called 'Hue Middle'. The variable 'Hue Range' will tell how much has to be displayed of the colors directly to the left and right of whatever you have selected as Hue Middle.
Image

Nice Hue Middle values to try, but feel free to use whatever you like
Red: 0.0
Yellow: 0.167
Green: 0.333
Cyan: 0.5 (Skyrim sky color is somewhere around 0.55)
Blue: 0.667
Magenta: 0.833

Ie. If I want my picture to contain mainly blue's and green's I would select hue middle: 0.5 and set range 0.333, then I will get blue and green represented at 50% their normal saturation since the max value of hue range is the value at which it becomes greyscale. With the same logic; if I want only reds and exclude everything else I would set hue middle at 0.0 and range at 0.167 (or maybe even smaller if I absolutely don't want to see orange and purple hue's, like 0.083).

Version 1.1
- Modified code a little (cleaner)
- Extended Hue Range from 0.5 max to 1.0 max. At 1.0 max you can use the inverted effect so instead of filtering everything out except a certain color, you can now filter out a certain color and leave everything else in place as well.
Version 1.2
- Bugfix in higher hue ranges, they should react normal now (pink, purples and reds)
- Code changes, other method to calculate Hue and Saturation which is more efficient on GPU
- Can't see any more problems with it, so should be final
Version 1.3
- Added HSL controls on request, need to replace entire code
Version 1.4
- Reworked code to be cleaner and more efficient

Use as you see fit, credits would be appreciated.

GUI elements

Code: Select all

float3 ccFilterLuma <string UIName="Color Filter: Luma";				string UIWidget="Color";	> = {0.2125, 0.7154, 0.0721};
float hueMid <		string UIName="Color Filter: Hue Middle";			string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float hueRange <	string UIName="Color Filter: Hue Range";			string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=0.9;	float UIStep=0.001;	> = {0.2};
float satLimit <	string UIName="Color Filter: Saturation Limit";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {1.0};
float fxcolorMix <	string UIName="Color Filter: Effect Strength";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {1.0};
float HueShiftD <	string UIName="Day HSL: Hue Shift";			string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float SaturationD <	string UIName="Day HSL: Saturation";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float LightnessD <	string UIName="Day HSL: Highlights";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float ShadowsD <	string UIName="Day HSL: Shadows";			string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float HueShiftN <	string UIName="Night HSL: Hue Shift";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float SaturationN <	string UIName="Night HSL: Saturation";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float LightnessN <	string UIName="Night HSL: Highlights";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float ShadowsN <	string UIName="Night HSL: Shadows";			string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float HueShiftI <	string UIName="Interior HSL: Hue Shift";	string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float SaturationI <	string UIName="Interior HSL: Saturation";	string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float LightnessI <	string UIName="Interior HSL: Highlights";	string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
float ShadowsI <	string UIName="Interior HSL: Shadows";		string UIWidget="Spinner";	float UIMin=0.0;	float UIMax=1.0;	float UIStep=0.001;	> = {0.0};
Helper functions - need to be placed OUTSIDE of the pixel shader

Code: Select all

float smootherstep(float edge0, float edge1, float x)
{
	x = clamp((x - edge0)/(edge1 - edge0), 0.0, 1.0);
	return x*x*x*(x*(x*6 - 15) + 10);
}

float3 HUEToRGB(in float H)
{
	float R = abs(H * 6 - 3) - 1;
	float G = 2 - abs(H * 6 - 2);
	float B = 2 - abs(H * 6 - 4);
	return saturate(float3(R,G,B));
}

float Epsilon = 1e-10;

float3 RGBToHCV(in float3 RGB)
{
	// Based on work by Sam Hocevar and Emil Persson
	float4 P = (RGB.g < RGB.b) ? float4(RGB.bg, -1.0, 2.0/3.0) : float4(RGB.gb, 0.0, -1.0/3.0);
	float4 Q = (RGB.r < P.x) ? float4(P.xyw, RGB.r) : float4(RGB.r, P.yzx);
	float C = Q.x - min(Q.w, Q.y);
	float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
	return float3(H, C, Q.x);
}

float3 RGBToHSL(in float3 RGB)
{
	float3 HCV = RGBToHCV(RGB);
	float L = HCV.z - HCV.y * 0.5;
	float S = HCV.y / (1 - abs(L * 2 - 1) + Epsilon);
	return float3(HCV.x, S, L);
}

float3 HSLToRGB(in float3 HSL)
{
	float3 RGB = HUEToRGB(HSL.x);
	float C = (1 - abs(2 * HSL.z - 1)) * HSL.y;
	return (RGB - 0.5) * C + HSL.z;
}
And the code for the actual effect. I am sure it can be done nicer, but this is fully functional - place inside Pixel Shader, needs to be the last effect related to coloring (in enbeffect.fx OR effect.txt, whichever contains the last). IF you have vibrancy effect you should place this before vibrancy. That will allow added controls. For example: You can use the effect to emphasize certain colors... say I select a hue of 0.5 (blue) and a range around that. Then I desaturate the surrounding just a little bit using the effect strength so blue hue's really stand out. And right after I do a vibrancy effect to pull the surroundings back to normal levels and the result would be strong blues without tinting the other colors to blue as a normal "color balance" tweak would do.

HSL Filter will work with curves and not plain adding/subtracting stuff because that's better left to Level controls.

Code: Select all

//COLOR ISOLATION FILTER
float4 r0; float r1; float2 r2;
r0.xyz=saturate(color.xyz);
r0.w=dot(r0.xyz, ccFilterLuma.xyz/dot(ccFilterLuma.xyz, 1));
r1.x=RGBToHSL(r0.xyz).x;
r2.xy=float2(hueMid-hueRange, hueMid+hueRange);
if(r2.y>1 && r1.x<r2.y-1)
	r1.x+=1;
if(r2.x<0 && r1.x>r2.x+1)
	r1.x-=1;
if(r1.x<hueMid)
	r0.xyz=lerp(r0.w, r0.xyz, smootherstep(r2.x, hueMid, r1.x)*satLimit);
if(r1.x>=hueMid)
	r0.xyz=lerp(r0.w, r0.xyz, (1-smootherstep(hueMid, r2.y, r1.x))*satLimit);
color.xyz=lerp(color.xyz, r0.xyz, fxcolorMix);

//HSL EFFECTS
r0.xyzw=lerp(lerp(float4(HueShiftN, SaturationN, LightnessN, ShadowsN), float4(HueShiftD, SaturationD, LightnessD, ShadowsD), ENightDayFactor), float4(HueShiftI, SaturationI, LightnessI, ShadowsI), EInteriorFactor);
color.xyz=RGBToHSL(saturate(color.xyz));
color.x=color.x+color.x-step(1, color.x+r0.x);
color.y=color.y+((1-color.y)*(r0.y*color.y));
color.z=color.z+((1-color.z)*(r0.z*color.z));
color.z=color.z+((1-color.z)*(r0.w*(1-color.z)));
color.xyz=HSLToRGB(saturate(color.xyz));
Just a simple example shot, you could filter out any color you want and depending on the range of the effect leave certain hue's in place.

Image

Image

Image

I hope you enjoy :mrgreen:

Cheers.
Last edited by prod80 on 04 Feb 2015, 01:24, edited 35 times in total.

Offline
User avatar
*master*
Posts: 106
Joined: 01 May 2013, 23:17

Re: [CODE INC] Color Filter - Sin City style effect!

Thank you for this great effect :) I've been waiting for it ages as you know :D

Offline
*sensei*
Posts: 372
Joined: 28 Jul 2013, 23:26

Re: [CODE INC] Color Filter - Sin City style effect!

Welcome Tali :)

I forgot a piece of code (grayValue function, but I think it's already in your file) ... updated now so it's complete.

Offline
*blah-blah-blah maniac*
Posts: 504
Joined: 31 Dec 2011, 19:42

Re: [HLSL CODE] Effect: Color Filter - Channel Isolation

Thanks! Already incorporated this and it's great.
_________________
NLA v.2.0 beta - A test version of the latest NLA release.
Natural Lighting and Atmospherics for ENB - A Skyrim weather mod and preset.
High-Res bark textures - Some bark textures I made.
Dark Souls 2 ENB preset - Preset for Dark Souls 2.

Offline
*sensei*
Posts: 372
Joined: 28 Jul 2013, 23:26

Re: [HLSL CODE] Effect: Color Filter - Channel Isolation - v

Thanks CM!

Now with bugfixes :D

Offline
User avatar
*blah-blah-blah maniac*
Posts: 1034
Joined: 15 Mar 2013, 10:24
Location: Earth

Re: [HLSL CODE] Effect: Color Filter - Channel Isolation - v

prod80
hey, is there an already complied effect.fx file? would love to try it out but don't know how or where to put those codes :(
_________________
cpu Ryzen 5 3600 gpu RTX 3070 ram 32GB os Win11 64

Flickr Gallery

Offline
*sensei*
Posts: 372
Joined: 28 Jul 2013, 23:26

Re: [HLSL CODE] Effect: Color Filter - Channel Isolation - v

You could try this one (fx + fx.ini) in Serenity ENB 8.2, the main version without changed colors, ofcourse
<link removed>

The effect in GUI is called "Color Filter"

cheers
Last edited by prod80 on 16 Aug 2014, 16:48, edited 1 time in total.

Offline
User avatar
*blah-blah-blah maniac*
Posts: 1034
Joined: 15 Mar 2013, 10:24
Location: Earth

Re: [HLSL CODE] Effect: Color Filter - Channel Isolation - v

thanks, i'll give it a go ;)
_________________
cpu Ryzen 5 3600 gpu RTX 3070 ram 32GB os Win11 64

Flickr Gallery

Offline
Posts: 2
Joined: 16 Aug 2014, 22:51

Re: [HLSL CODE] Effect: Color Filter - Channel Isolation - v

Hi !
Sorry I'm a noob but very interested in your Sin City effect, that is handsome ! :D
BUT, how to do it ? I mean, where do I have to copy your code ? I'm completely lost..
Thanks a lot :)

Offline
*sensei*
Posts: 372
Joined: 28 Jul 2013, 23:26

Re: [HLSL CODE] Effect: Color Filter - Channel Isolation - v

Well the code has to be placed inside of enbeffect.fx file. It's not copied here so that I can do that for everyone... It's here for ENB tweakers. So, unless someone releases an ENB with that code inside you'll have to find someone with HLSL knowledge willing to do it for you. Pretty sure one of these days an ENB becomes available with that code inside. Probably my own (Serenity ENB) will get an update when I feel like it, and then this code will be available with that ENB.
Post Reply