obs-StreamFX/data/effects/lut.effect

134 lines
4.1 KiB
Plaintext

// AUTOGENERATED COPYRIGHT HEADER START
// Copyright (C) 2021-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
// AUTOGENERATED COPYRIGHT HEADER END
sampler_state __LUTSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
float4 generate_lut(uint bit_depth, float2 uv) {
uint size = pow(2, bit_depth);
uint z_size = pow(2, bit_depth / 2);
uint container_size = pow(2, bit_depth + (bit_depth / 2));
uint2 xy = uint2(floor(uv * container_size));
uint2 rg = xy % size;
uint2 bb = xy / size;
return float4(
rg.xy / float(size - 1),
((bb.y * z_size) + bb.x) / float(size - 1),
1.
);
};
float4 generate_lut2(float2 uv, uint4 params0) {
uint size = params0.r;
uint z_size = params0.g;
uint container_size = params0.b;
uint2 xy = uint2(floor(uv * container_size));
uint2 rg = xy % size;
uint2 bb = xy / size;
return float4(
rg.xy / float(size - 1),
((bb.y * z_size) + bb.x) / float(size - 1),
1.
);
};
float3 sample_lut(float3 color, uint bit_depth, texture2d lut_texture) {
uint size = pow(2, bit_depth);
uint z_size = pow(2, bit_depth / 2);
uint container_size = pow(2, bit_depth + (bit_depth / 2));
float inverse_size = 1. / size;
float inverse_z_size = 1. / z_size;
float inverse_container_size = 1. / container_size;
float half_texel = inverse_container_size / 2.; // Linear sampling is weird.
// Due to our LUT not actually being a cube but a plane pretending to be a cube,
// we have to do some conversion into the grid structure in order to be successful.
// 1. Clamp everything to a reasonable range.
color = saturate(color);
// 2. Rescale everything into 0..(size - 1)
color *= (size - 1);
// 3. Convert red and green into initial grid cell UVs.
float2 xy_uv = color.xy * inverse_container_size;
// 4. Figure out the high and low parts for interpolation.
uint z_lo = floor(color.z);
uint z_hi = z_lo + 1;
// 5. Figure out the X location of the cell in the grid.
uint z_lo_x = z_lo % z_size;
uint z_hi_x = z_hi % z_size;
// 6. Figure out the Y location of the cell in the grid.
uint z_lo_y = z_lo / z_size;
uint z_hi_y = z_hi / z_size;
// 7. Convert the X and Y locations into UV coordinates.
float2 z_lo_uv = float2(z_lo_x, z_lo_y) * inverse_z_size;
float2 z_hi_uv = float2(z_hi_x, z_hi_y) * inverse_z_size;
// 8. Sample both low and high points.
float3 c_lo = lut_texture.Sample(__LUTSampler, xy_uv + z_lo_uv + half_texel).rgb;
float3 c_hi = lut_texture.Sample(__LUTSampler, xy_uv + z_hi_uv + half_texel).rgb;
// 9. Return an interpolated version based on the fraction of Z.
return lerp(c_lo, c_hi, frac(color.z));
};
float3 sample_lut2(float3 color, texture2d lut_texture, int4 params0, float4 params1) {
uint size = params0.r;
uint z_size = params0.g;
uint container_size = params0.b;
float inverse_size = params1.r;
float inverse_z_size = params1.g;
float inverse_container_size = params1.b;
float half_texel = params1.a;
// Due to our LUT not actually being a cube but a plane pretending to be a cube,
// we have to do some conversion into the grid structure in order to be successful.
// 1. Clamp everything to a reasonable range.
color = saturate(color);
// 2. Rescale everything into 0..(size - 1)
color *= (size - 1);
// 3. Convert red and green into initial grid cell UVs.
float2 xy_uv = color.xy * inverse_container_size;
// 4. Figure out the high and low parts for interpolation.
uint z_lo = floor(color.z);
uint z_hi = z_lo + 1;
// 5. Figure out the X location of the cell in the grid.
uint z_lo_x = z_lo % z_size;
uint z_hi_x = z_hi % z_size;
// 6. Figure out the Y location of the cell in the grid.
uint z_lo_y = z_lo / z_size;
uint z_hi_y = z_hi / z_size;
// 7. Convert the X and Y locations into UV coordinates.
float2 z_lo_uv = float2(z_lo_x, z_lo_y) * inverse_z_size;
float2 z_hi_uv = float2(z_hi_x, z_hi_y) * inverse_z_size;
// 8. Sample both low and high points.
float3 c_lo = lut_texture.Sample(__LUTSampler, xy_uv + z_lo_uv + half_texel).rgb;
float3 c_hi = lut_texture.Sample(__LUTSampler, xy_uv + z_hi_uv + half_texel).rgb;
// 9. Return an interpolated version based on the fraction of Z.
return lerp(c_lo, c_hi, frac(color.z));
};