Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 63 additions & 59 deletions impeller/compiler/shader_lib/impeller/blending.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,48 @@

#include <impeller/branching.glsl>
#include <impeller/constants.glsl>
#include <impeller/types.glsl>

//------------------------------------------------------------------------------
/// HSV utilities.
///

float IPLuminosity(vec3 color) {
return color.r * 0.3 + color.g * 0.59 + color.b * 0.11;
float16_t IPLuminosity(f16vec3 color) {
return color.r * 0.3hf + color.g * 0.59hf + color.b * 0.11hf;
}

/// Scales the color's luma by the amount necessary to place the color
/// components in a 1-0 range.
vec3 IPClipColor(vec3 color) {
float lum = IPLuminosity(color);
float mn = min(min(color.r, color.g), color.b);
float mx = max(max(color.r, color.g), color.b);
f16vec3 IPClipColor(f16vec3 color) {
float16_t lum = IPLuminosity(color);
float16_t mn = min(min(color.r, color.g), color.b);
float16_t mx = max(max(color.r, color.g), color.b);
// `lum - mn` and `mx - lum` will always be >= 0 in the following conditions,
// so adding a tiny value is enough to make these divisions safe.
if (mn < 0) {
if (mn < 0.0hf) {
color = lum + (((color - lum) * lum) / (lum - mn + kEhCloseEnough));
}
if (mx > 1) {
color = lum + (((color - lum) * (1 - lum)) / (mx - lum + kEhCloseEnough));
if (mx > 1.0hf) {
color =
lum + (((color - lum) * (1.0hf - lum)) / (mx - lum + kEhCloseEnough));
}
return color;
}

vec3 IPSetLuminosity(vec3 color, float luminosity) {
float relative_lum = luminosity - IPLuminosity(color);
f16vec3 IPSetLuminosity(f16vec3 color, float16_t luminosity) {
float16_t relative_lum = luminosity - IPLuminosity(color);
return IPClipColor(color + relative_lum);
}

float IPSaturation(vec3 color) {
float16_t IPSaturation(f16vec3 color) {
return max(max(color.r, color.g), color.b) -
min(min(color.r, color.g), color.b);
}

vec3 IPSetSaturation(vec3 color, float saturation) {
float mn = min(min(color.r, color.g), color.b);
float mx = max(max(color.r, color.g), color.b);
return (mn < mx) ? ((color - mn) * saturation) / (mx - mn) : vec3(0);
f16vec3 IPSetSaturation(f16vec3 color, float16_t saturation) {
float16_t mn = min(min(color.r, color.g), color.b);
float16_t mx = max(max(color.r, color.g), color.b);
return (mn < mx) ? ((color - mn) * saturation) / (mx - mn) : f16vec3(0.0hf);
}

//------------------------------------------------------------------------------
Expand All @@ -58,134 +60,136 @@ vec3 IPSetSaturation(vec3 color, float saturation) {
/// applied to the destination using `SourceOver` alpha compositing.
///

vec3 IPBlendScreen(vec3 dst, vec3 src) {
f16vec3 IPBlendScreen(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingscreen
return dst + src - (dst * src);
}

vec3 IPBlendHardLight(vec3 dst, vec3 src) {
f16vec3 IPBlendHardLight(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendinghardlight
return IPVec3Choose(dst * (2 * src), IPBlendScreen(dst, 2 * src - 1), src);
return IPVec3Choose(dst * (2.0hf * src),
IPBlendScreen(dst, 2.0hf * src - 1.0hf), src);
}

vec3 IPBlendOverlay(vec3 dst, vec3 src) {
f16vec3 IPBlendOverlay(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingoverlay
// HardLight, but with reversed parameters.
return IPBlendHardLight(src, dst);
}

vec3 IPBlendDarken(vec3 dst, vec3 src) {
f16vec3 IPBlendDarken(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingdarken
return min(dst, src);
}

vec3 IPBlendLighten(vec3 dst, vec3 src) {
f16vec3 IPBlendLighten(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendinglighten
return max(dst, src);
}

vec3 IPBlendColorDodge(vec3 dst, vec3 src) {
f16vec3 IPBlendColorDodge(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingcolordodge

vec3 color = min(vec3(1), dst / (1 - src));
f16vec3 color = min(f16vec3(1.0hf), dst / (1.0hf - src));

if (dst.r < kEhCloseEnough) {
color.r = 0;
color.r = 0.0hf;
}
if (dst.g < kEhCloseEnough) {
color.g = 0;
color.g = 0.0hf;
}
if (dst.b < kEhCloseEnough) {
color.b = 0;
color.b = 0.0hf;
}

if (1 - src.r < kEhCloseEnough) {
color.r = 1;
if (1.0hf - src.r < kEhCloseEnough) {
color.r = 1.0hf;
}
if (1 - src.g < kEhCloseEnough) {
color.g = 1;
if (1.0hf - src.g < kEhCloseEnough) {
color.g = 1.0hf;
}
if (1 - src.b < kEhCloseEnough) {
color.b = 1;
if (1.0hf - src.b < kEhCloseEnough) {
color.b = 1.0hf;
}

return color;
}

vec3 IPBlendColorBurn(vec3 dst, vec3 src) {
f16vec3 IPBlendColorBurn(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingcolorburn

vec3 color = 1 - min(vec3(1), (1 - dst) / src);
f16vec3 color = 1.0hf - min(f16vec3(1.0hf), (1.0hf - dst) / src);

if (1 - dst.r < kEhCloseEnough) {
color.r = 1;
if (1.0hf - dst.r < kEhCloseEnough) {
color.r = 1.0hf;
}
if (1 - dst.g < kEhCloseEnough) {
color.g = 1;
if (1.0hf - dst.g < kEhCloseEnough) {
color.g = 1.0hf;
}
if (1 - dst.b < kEhCloseEnough) {
color.b = 1;
if (1.0hf - dst.b < kEhCloseEnough) {
color.b = 1.0hf;
}

if (src.r < kEhCloseEnough) {
color.r = 0;
color.r = 0.0hf;
}
if (src.g < kEhCloseEnough) {
color.g = 0;
color.g = 0.0hf;
}
if (src.b < kEhCloseEnough) {
color.b = 0;
color.b = 0.0hf;
}

return color;
}

vec3 IPBlendSoftLight(vec3 dst, vec3 src) {
f16vec3 IPBlendSoftLight(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingsoftlight

vec3 D = IPVec3ChooseCutoff(((16 * dst - 12) * dst + 4) * dst, //
sqrt(dst), //
dst, //
0.25);
f16vec3 D =
IPVec3ChooseCutoff(((16.0hf * dst - 12.0hf) * dst + 4.0hf) * dst, //
sqrt(dst), //
dst, //
0.25hf);

return IPVec3Choose(dst - (1 - 2 * src) * dst * (1 - dst), //
dst + (2 * src - 1) * (D - dst), //
return IPVec3Choose(dst - (1.0hf - 2.0hf * src) * dst * (1.0hf - dst), //
dst + (2.0hf * src - 1.0hf) * (D - dst), //
src);
}

vec3 IPBlendDifference(vec3 dst, vec3 src) {
f16vec3 IPBlendDifference(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingdifference
return abs(dst - src);
}

vec3 IPBlendExclusion(vec3 dst, vec3 src) {
f16vec3 IPBlendExclusion(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingexclusion
return dst + src - 2 * dst * src;
return dst + src - 2.0hf * dst * src;
}

vec3 IPBlendMultiply(vec3 dst, vec3 src) {
f16vec3 IPBlendMultiply(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingmultiply
return dst * src;
}

vec3 IPBlendHue(vec3 dst, vec3 src) {
f16vec3 IPBlendHue(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendinghue
return IPSetLuminosity(IPSetSaturation(src, IPSaturation(dst)),
IPLuminosity(dst));
}

vec3 IPBlendSaturation(vec3 dst, vec3 src) {
f16vec3 IPBlendSaturation(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingsaturation
return IPSetLuminosity(IPSetSaturation(dst, IPSaturation(src)),
IPLuminosity(dst));
}

vec3 IPBlendColor(vec3 dst, vec3 src) {
f16vec3 IPBlendColor(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingcolor
return IPSetLuminosity(src, IPLuminosity(dst));
}

vec3 IPBlendLuminosity(vec3 dst, vec3 src) {
f16vec3 IPBlendLuminosity(f16vec3 dst, f16vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingluminosity
return IPSetLuminosity(dst, IPLuminosity(src));
}
Expand Down
33 changes: 18 additions & 15 deletions impeller/compiler/shader_lib/impeller/branching.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,45 @@
/// Perform an equality check for each vec3 component.
///
/// Returns 1.0 if x == y, otherwise 0.0.
BoolV3 IPVec3IsEqual(vec3 x, float y) {
vec3 diff = abs(x - y);
return vec3(diff.r < kEhCloseEnough, //
diff.g < kEhCloseEnough, //
diff.b < kEhCloseEnough);
BoolV3 IPVec3IsEqual(f16vec3 x, float16_t y) {
f16vec3 diff = abs(x - y);
return f16vec3(diff.r < kEhCloseEnough, //
diff.g < kEhCloseEnough, //
diff.b < kEhCloseEnough);
}

/// Perform a branchless greater than check.
///
/// Returns 1.0 if x > y, otherwise 0.0.
BoolF IPFloatIsGreaterThan(float x, float y) {
return max(sign(x - y), 0);
BoolF IPFloatIsGreaterThan(float16_t x, float16_t y) {
return max(sign(x - y), 0.0hf);
}

/// Perform a branchless greater than check for each vec3 component.
///
/// Returns 1.0 if x > y, otherwise 0.0.
BoolV3 IPVec3IsGreaterThan(vec3 x, vec3 y) {
return max(sign(x - y), 0);
BoolV3 IPVec3IsGreaterThan(f16vec3 x, f16vec3 y) {
return max(sign(x - y), 0.0hf);
}

/// Perform a branchless less than check.
///
/// Returns 1.0 if x < y, otherwise 0.0.
BoolF IPFloatIsLessThan(float x, float y) {
return max(sign(y - x), 0);
BoolF IPFloatIsLessThan(float16_t x, float16_t y) {
return max(sign(y - x), 0.0hf);
}

/// For each vec3 component, if value > cutoff, return b, otherwise return a.
vec3 IPVec3ChooseCutoff(vec3 a, vec3 b, vec3 value, float cutoff) {
return mix(a, b, IPVec3IsGreaterThan(value, vec3(cutoff)));
f16vec3 IPVec3ChooseCutoff(f16vec3 a,
f16vec3 b,
f16vec3 value,
float16_t cutoff) {
return mix(a, b, IPVec3IsGreaterThan(value, f16vec3(cutoff)));
}

/// For each vec3 component, if value > 0.5, return b, otherwise return a.
vec3 IPVec3Choose(vec3 a, vec3 b, vec3 value) {
return IPVec3ChooseCutoff(a, b, value, 0.5);
f16vec3 IPVec3Choose(f16vec3 a, f16vec3 b, f16vec3 value) {
return IPVec3ChooseCutoff(a, b, value, 0.5hf);
}

#endif
13 changes: 7 additions & 6 deletions impeller/compiler/shader_lib/impeller/color.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@
#define COLOR_GLSL_

#include <impeller/branching.glsl>
#include <impeller/types.glsl>

/// Convert a premultiplied color (a color which has its color components
/// multiplied with its alpha value) to an unpremultiplied color.
///
/// Returns (0, 0, 0, 0) if the alpha component is 0.
vec4 IPUnpremultiply(vec4 color) {
if (color.a == 0) {
return vec4(0);
f16vec4 IPUnpremultiply(f16vec4 color) {
if (color.a == 0.0hf) {
return f16vec4(0.0hf);
}
return vec4(color.rgb / color.a, color.a);
return f16vec4(color.rgb / color.a, color.a);
}

/// Convert an unpremultiplied color (a color which has its color components
/// separated from its alpha value) to a premultiplied color.
///
/// Returns (0, 0, 0, 0) if the alpha component is 0.
vec4 IPPremultiply(vec4 color) {
return vec4(color.rgb * color.a, color.a);
f16vec4 IPPremultiply(f16vec4 color) {
return f16vec4(color.rgb * color.a, color.a);
}

#endif
10 changes: 6 additions & 4 deletions impeller/compiler/shader_lib/impeller/constants.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
#ifndef CONSTANTS_GLSL_
#define CONSTANTS_GLSL_

const float kEhCloseEnough = 0.000001;
#include <impeller/types.glsl>

const float16_t kEhCloseEnough = 0.000001hf;

// 1 / (2 * pi)
const float k1Over2Pi = 0.1591549430918;
const float16_t k1Over2Pi = 0.1591549430918hf;

// sqrt(2 * pi)
const float kSqrtTwoPi = 2.50662827463;
const float16_t kSqrtTwoPi = 2.50662827463hf;

// sqrt(2) / 2 == 1 / sqrt(2)
const float kHalfSqrtTwo = 0.70710678118;
const float16_t kHalfSqrtTwo = 0.70710678118hf;

#endif
Loading