done with blend modes

This commit is contained in:
lachrymaLF 2024-06-06 15:45:27 -04:00
parent facd0d7022
commit 151d10671b
2 changed files with 100 additions and 46 deletions

View file

@ -1,4 +1,4 @@
/* Reference: https://drafts.fxtf.org/compositing-1 */
/* Reference: https://drafts.fxtf.org/compositing-1, https://www.shadertoy.com/view/XdS3RW */
$input v_texcoord0
@ -9,6 +9,44 @@ uniform vec4 u_mode;
SAMPLER2D(s_A, 0);
SAMPLER2D(s_B, 1);
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0f, -1.0f / 3.0f, 2.0f / 3.0f, -1.0f);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0f * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0f, 2.0f / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0f - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0f, 1.0f), c.y);
}
float Overlay(float s, float d) {
return (d < 0.5) ? 2.0 * s * d : 1.0 - 2.0 * (1.0 - s) * (1.0 - d);
}
float HardLight(float s, float d) {
return (s < 0.5) ? 2.0 * s * d : 1.0 - 2.0 * (1.0 - s) * (1.0 - d);
}
float SoftLight(float s, float d) {
return (s < 0.5) ? d - (1.0 - 2.0 * s) * d * (1.0 - d)
: (d < 0.25) ? d + (2.0 * s - 1.0) * d * ((16.0 * d - 12.0) * d + 4.0)
: d + (2.0 * s - 1.0) * (sqrt(d) - d);
}
float VividLight(float s, float d) {
return (s < 0.5) ? 1.0 - (1.0 - d) / (2.0 * s) : d / (2.0 * (1.0 - s));
}
float PinLight(float s, float d){
return (2.0 * s - 1.0 > d) ? 2.0 * s - 1.0 : (s < 0.5 * d) ? 2.0 * s : d;
}
void main() {
vec2 uv = vec2(v_texcoord0.x, 1.0f - v_texcoord0.y);
vec4 _A = texture2D(s_A, uv);
@ -41,68 +79,85 @@ void main() {
else if (mode == 5) { // Exclusion
blend = _B.xyz + _A.xyz - 2.0f * _B.xyz * _A.xyz;
}
else if (mode == 6) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 6) { // Multiply
blend = _A.xyz * _B.xyz;
}
else if (mode == 7) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 7) { // Divide
blend = _A.xyz / _B.xyz;
}
else if (mode == 8) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 8) { // Lighten
blend = max(_A.xyz, _B.xyz);
}
else if (mode == 9) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 9) { // Darken
blend = min(_A.xyz, _B.xyz);
}
else if (mode == 10) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 10) { // Lighter Colour -- Why do these two use l1 instead of l2?
blend = (_A.x + _A.y + _A.z > _B.x + _B.y + _B.z) ? _A.xyz : _B.xyz;
}
else if (mode == 11) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 11) { // Darker Colour
blend = (_A.x + _A.y + _A.z < _B.x + _B.y + _B.z) ? _A.xyz : _B.xyz;
}
else if (mode == 12) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 12) { // Screen
blend = _A.xyz + _B.xyz - _A.xyz * _B.xyz;
}
else if (mode == 13) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 13) { // Overlay
blend = vec3(Overlay(_A.x, _B.x), Overlay(_A.y, _B.y), Overlay(_A.z, _B.z));
}
else if (mode == 14) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 14) { // Hard Light
blend = vec3(HardLight(_A.x, _B.x), HardLight(_A.y, _B.y), HardLight(_A.z, _B.z));
}
else if (mode == 15) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 15) { // Soft Light
blend = vec3(SoftLight(_A.x, _B.x), SoftLight(_A.y, _B.y), SoftLight(_A.z, _B.z));
}
else if (mode == 16) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 16) { // Vivid Light
blend = vec3(VividLight(_A.x, _B.x), VividLight(_A.y, _B.y), VividLight(_A.z, _B.z));
}
else if (mode == 17) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 17) { // Linear Light
blend = 2.0f * _A.xyz + _B.xyz - 1.0f;
}
else if (mode == 18) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 18) { // Pin Light
blend = vec3(PinLight(_A.x, _B.x), PinLight(_A.y, _B.y), PinLight(_A.z, _B.z));
}
else if (mode == 19) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 19) { // Colour Burn
blend = 1.0f - (1.0f - _B.xyz) / _A.xyz;
}
else if (mode == 20) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 20) { // Linear Burn
blend = _A.xyz + _B.xyz - 1.0f;
}
else if (mode == 21) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 21) { // Colour Dodge
blend = _B.xyz / (1.0f - _A.xyz);
}
else if (mode == 22) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 22) { // Hue
vec3 d = rgb2hsv(_B.xyz);
d.x = rgb2hsv(_A.xyz).x;
blend = hsv2rgb(d);
}
else if (mode == 23) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 23) { // Saturation
vec3 d = rgb2hsv(_B.xyz);
d.y = rgb2hsv(_A.xyz).y;
blend = hsv2rgb(d);
}
else if (mode == 24) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 24) { // Colour
vec3 s = rgb2hsv(_A.xyz);
s.z = rgb2hsv(_B.xyz).z;
blend = hsv2rgb(s);
}
else if (mode == 25) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
else if (mode == 25) { // Luminosity
float dLum = dot(_B.xyz, vec3(0.3, 0.59, 0.11));
float sLum = dot(_A.xyz, vec3(0.3, 0.59, 0.11));
float lum = sLum - dLum;
vec3 c = _B.xyz + lum;
float minC = min(min(c.x, c.y), c.z);
float maxC = max(max(c.x, c.y), c.z);
if (minC < 0.0)
blend = sLum + ((c - sLum) * sLum) / (sLum - minC);
else if (maxC > 1.0)
blend = sLum + ((c - sLum) * (1.0 - sLum)) / (maxC - sLum);
else
blend = c;
}
else {
gl_FragColor = vec4(uv, 0.0f, 1.0f);
blend = vec3(uv, 0.0f);
}
// Porter-Duff Source Over

View file

@ -1,6 +1,5 @@
# NOW
## Chores
- actually write the blending modes (everything is just alpha over right now)
- Node groups
## Compositor
@ -16,11 +15,11 @@
- Motion blur
## UI
- Viewport gizmos (Layer-specific & nodes -- can separate into different tools?) -- Not sure how to go about this
- Node loop detection (separate DFS (extra work) or be smart in recursion)
- detect time-sensitive nodes in tree and display on timeline
- Key selection in comp panel
- Graph editor
- Node loop detection (separate DFS (extra work) or be smart in recursion)
- detect time-sensitive nodes in tree and display on timeline
- Viewport gizmos (Layer-specific & nodes -- can separate into different tools?) -- Not sure how to go about this
# Later
## Compositor