| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- #include "../StdLib.hlsl"
- #include "../Colors.hlsl"
- #include "../ACES.hlsl"
- #pragma kernel KGenLut3D_NoTonemap TONEMAPPING_NONE
- #pragma kernel KGenLut3D_AcesTonemap TONEMAPPING_ACES
- #pragma kernel KGenLut3D_NeutralTonemap TONEMAPPING_NEUTRAL
- #pragma kernel KGenLut3D_CustomTonemap TONEMAPPING_CUSTOM
- RWTexture3D<float4> _Output;
- CBUFFER_START(Params)
- float4 _Size; // x: lut_size, y: 1 / (lut_size - 1), zw: unused
- float4 _ColorBalance;
- float4 _ColorFilter;
- float4 _HueSatCon;
- float4 _ChannelMixerRed;
- float4 _ChannelMixerGreen;
- float4 _ChannelMixerBlue;
- float4 _Lift;
- float4 _InvGamma;
- float4 _Gain;
- float4 _CustomToneCurve;
- // Packing is currently borked, can't pass float arrays without it creating one vector4 per
- // float so we'll pack manually...
- float4 _ToeSegmentA;
- float4 _ToeSegmentB;
- float4 _MidSegmentA;
- float4 _MidSegmentB;
- float4 _ShoSegmentA;
- float4 _ShoSegmentB;
- CBUFFER_END
- Texture2D _Curves;
- SamplerState sampler_Curves;
- float3 LogGrade(float3 colorLog)
- {
- // Contrast feels a lot more natural when done in log rather than doing it in linear
- colorLog = Contrast(colorLog, ACEScc_MIDGRAY, _HueSatCon.z);
- return colorLog;
- }
- float3 LinearGrade(float3 colorLinear)
- {
- colorLinear = WhiteBalance(colorLinear, _ColorBalance.rgb);
- colorLinear *= _ColorFilter.rgb;
- colorLinear = ChannelMixer(colorLinear, _ChannelMixerRed.rgb, _ChannelMixerGreen.rgb, _ChannelMixerBlue.rgb);
- colorLinear = LiftGammaGainHDR(colorLinear, _Lift.rgb, _InvGamma.rgb, _Gain.rgb);
- // Do NOT feed negative values to RgbToHsv or they'll wrap around
- colorLinear = max(0.0, colorLinear);
- float3 hsv = RgbToHsv(colorLinear);
- // Hue Vs Sat
- float satMult;
- satMult = saturate(_Curves.SampleLevel(sampler_Curves, float2(hsv.x, 0.25), 0).y) * 2.0;
- // Sat Vs Sat
- satMult *= saturate(_Curves.SampleLevel(sampler_Curves, float2(hsv.y, 0.25), 0).z) * 2.0;
- // Lum Vs Sat
- satMult *= saturate(_Curves.SampleLevel(sampler_Curves, float2(Luminance(colorLinear), 0.25), 0).w) * 2.0;
- // Hue Vs Hue
- float hue = hsv.x + _HueSatCon.x;
- float offset = saturate(_Curves.SampleLevel(sampler_Curves, float2(hue, 0.25), 0).x) - 0.5;
- hue += offset;
- hsv.x = RotateHue(hue, 0.0, 1.0);
- colorLinear = HsvToRgb(hsv);
- colorLinear = Saturation(colorLinear, _HueSatCon.y * satMult);
- return colorLinear;
- }
- #if TONEMAPPING_ACES
- float3 ColorGrade(float3 colorLutSpace)
- {
- float3 colorLinear = LUT_SPACE_DECODE(colorLutSpace);
- float3 aces = unity_to_ACES(colorLinear);
- // ACEScc (log) space
- float3 acescc = ACES_to_ACEScc(aces);
- acescc = LogGrade(acescc);
- aces = ACEScc_to_ACES(acescc);
- // ACEScg (linear) space
- float3 acescg = ACES_to_ACEScg(aces);
- acescg = LinearGrade(acescg);
- // Tonemap ODT(RRT(aces))
- aces = ACEScg_to_ACES(acescg);
- colorLinear = AcesTonemap(aces);
- return colorLinear;
- }
- #else
- float3 ColorGrade(float3 colorLutSpace)
- {
- // colorLutSpace is already in log space
- colorLutSpace = LogGrade(colorLutSpace);
- // Switch back to linear
- float3 colorLinear = LUT_SPACE_DECODE(colorLutSpace);
- colorLinear = LinearGrade(colorLinear);
- colorLinear = max(0.0, colorLinear);
- // Tonemap
- #if TONEMAPPING_NEUTRAL
- {
- colorLinear = NeutralTonemap(colorLinear);
- }
- #elif TONEMAPPING_CUSTOM
- {
- colorLinear = CustomTonemap(
- colorLinear, _CustomToneCurve.xyz,
- _ToeSegmentA, _ToeSegmentB.xy,
- _MidSegmentA, _MidSegmentB.xy,
- _ShoSegmentA, _ShoSegmentB.xy
- );
- }
- #endif
- return colorLinear;
- }
- #endif
- void Eval(uint3 id)
- {
- if (float(id.x) < _Size.x && float(id.y) < _Size.x && float(id.z) < _Size.x)
- {
- // Lut space (log space)
- float3 colorLutSpace = float3(id) * _Size.y;
- // Color grade & tonemap
- float3 graded = ColorGrade(colorLutSpace);
- _Output[id] = float4(max(graded, 0.0), 1.0);
- }
- }
- #define GROUP_SIZE 4
- #ifdef DISABLE_COMPUTE_SHADERS
- TRIVIAL_COMPUTE_KERNEL(KGenLut3D_NoTonemap)
- TRIVIAL_COMPUTE_KERNEL(KGenLut3D_AcesTonemap)
- TRIVIAL_COMPUTE_KERNEL(KGenLut3D_NeutralTonemap)
- TRIVIAL_COMPUTE_KERNEL(KGenLut3D_CustomTonemap)
- #else
- [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
- void KGenLut3D_NoTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
- [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
- void KGenLut3D_AcesTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
- [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
- void KGenLut3D_NeutralTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
- [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
- void KGenLut3D_CustomTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
- #endif // DISABLE_COMPUTE_SHADERS
|