From a8e33d3d3d6534b6ff0d252c6726ed2c58bdd7d1 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 25 Feb 2020 14:39:06 -0800 Subject: [PATCH] Add the soft light blend mode --- canvas/src/lib.rs | 2 + content/src/effects.rs | 4 + renderer/src/gpu/renderer.rs | 87 +++++++++++---- renderer/src/gpu/shaders.rs | 78 +++++++------ .../shaders/gl3/tile_alpha_softlight.fs.glsl | 82 ++++++++++++++ .../metal/tile_alpha_softlight.fs.metal | 105 ++++++++++++++++++ shaders/Makefile | 1 + shaders/tile_alpha_softlight.fs.glsl | 37 ++++++ 8 files changed, 342 insertions(+), 54 deletions(-) create mode 100644 resources/shaders/gl3/tile_alpha_softlight.fs.glsl create mode 100644 resources/shaders/metal/tile_alpha_softlight.fs.metal create mode 100644 shaders/tile_alpha_softlight.fs.glsl diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 5962b86a..bee13e10 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -541,6 +541,7 @@ pub enum CompositeOperation { ColorDodge, ColorBurn, HardLight, + SoftLight, Hue, Saturation, Color, @@ -568,6 +569,7 @@ impl CompositeOperation { CompositeOperation::ColorDodge => BlendMode::ColorDodge, CompositeOperation::ColorBurn => BlendMode::ColorBurn, CompositeOperation::HardLight => BlendMode::HardLight, + CompositeOperation::SoftLight => BlendMode::SoftLight, CompositeOperation::Hue => BlendMode::Hue, CompositeOperation::Saturation => BlendMode::Saturation, CompositeOperation::Color => BlendMode::Color, diff --git a/content/src/effects.rs b/content/src/effects.rs index 3f0ed9b0..84da569d 100644 --- a/content/src/effects.rs +++ b/content/src/effects.rs @@ -91,6 +91,9 @@ pub enum BlendMode { ColorDodge, ColorBurn, + // Soft light + SoftLight, + // HSL Hue, Saturation, @@ -139,6 +142,7 @@ impl BlendMode { BlendMode::Overlay | BlendMode::ColorDodge | BlendMode::ColorBurn | + BlendMode::SoftLight | BlendMode::Hue | BlendMode::Saturation | BlendMode::Color | diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index d3f4cff8..0d851cd1 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -10,7 +10,8 @@ use crate::gpu::debug::DebugUIPresenter; use crate::gpu::options::{DestFramebuffer, RendererOptions}; -use crate::gpu::shaders::{AlphaTileDodgeBurnProgram, AlphaTileHSLProgram, AlphaTileOverlayProgram}; +use crate::gpu::shaders::{AlphaTileBlendModeProgram, AlphaTileDodgeBurnProgram}; +use crate::gpu::shaders::{AlphaTileHSLProgram, AlphaTileOverlayProgram}; use crate::gpu::shaders::{AlphaTilePorterDuffProgram, AlphaTileProgram, AlphaTileVertexArray}; use crate::gpu::shaders::{CopyTileProgram, CopyTileVertexArray, FillProgram, FillVertexArray}; use crate::gpu::shaders::{FilterBasicProgram, FilterBasicVertexArray, FilterTextProgram}; @@ -86,6 +87,7 @@ where alpha_tile_porterduff_program: AlphaTilePorterDuffProgram, alpha_tile_overlay_program: AlphaTileOverlayProgram, alpha_tile_dodgeburn_program: AlphaTileDodgeBurnProgram, + alpha_tile_softlight_program: AlphaTileBlendModeProgram, alpha_tile_hsl_program: AlphaTileHSLProgram, mask_winding_tile_vertex_array: MaskTileVertexArray, mask_evenodd_tile_vertex_array: MaskTileVertexArray, @@ -95,6 +97,7 @@ where alpha_tile_porterduff_vertex_array: AlphaTileVertexArray, alpha_tile_overlay_vertex_array: AlphaTileVertexArray, alpha_tile_dodgeburn_vertex_array: AlphaTileVertexArray, + alpha_tile_softlight_vertex_array: AlphaTileVertexArray, alpha_tile_hsl_vertex_array: AlphaTileVertexArray, area_lut_texture: D::Texture, alpha_tile_vertex_buffer: D::Buffer, @@ -169,6 +172,9 @@ where let alpha_tile_porterduff_program = AlphaTilePorterDuffProgram::new(&device, resources); let alpha_tile_overlay_program = AlphaTileOverlayProgram::new(&device, resources); let alpha_tile_dodgeburn_program = AlphaTileDodgeBurnProgram::new(&device, resources); + let alpha_tile_softlight_program = AlphaTileBlendModeProgram::new(&device, + resources, + "tile_alpha_softlight"); let alpha_tile_hsl_program = AlphaTileHSLProgram::new(&device, resources); let filter_basic_program = FilterBasicProgram::new(&device, resources); let filter_text_program = FilterTextProgram::new(&device, resources); @@ -225,25 +231,31 @@ where ); let alpha_tile_porterduff_vertex_array = AlphaTileVertexArray::new( &device, - &alpha_tile_porterduff_program.alpha_tile_program, + &alpha_tile_porterduff_program.alpha_tile_blend_mode_program.alpha_tile_program, &alpha_tile_vertex_buffer, &quads_vertex_indices_buffer, ); let alpha_tile_overlay_vertex_array = AlphaTileVertexArray::new( &device, - &alpha_tile_overlay_program.alpha_tile_program, + &alpha_tile_overlay_program.alpha_tile_blend_mode_program.alpha_tile_program, &alpha_tile_vertex_buffer, &quads_vertex_indices_buffer, ); let alpha_tile_dodgeburn_vertex_array = AlphaTileVertexArray::new( &device, - &alpha_tile_dodgeburn_program.alpha_tile_program, + &alpha_tile_dodgeburn_program.alpha_tile_blend_mode_program.alpha_tile_program, + &alpha_tile_vertex_buffer, + &quads_vertex_indices_buffer, + ); + let alpha_tile_softlight_vertex_array = AlphaTileVertexArray::new( + &device, + &alpha_tile_softlight_program.alpha_tile_program, &alpha_tile_vertex_buffer, &quads_vertex_indices_buffer, ); let alpha_tile_hsl_vertex_array = AlphaTileVertexArray::new( &device, - &alpha_tile_hsl_program.alpha_tile_program, + &alpha_tile_hsl_program.alpha_tile_blend_mode_program.alpha_tile_program, &alpha_tile_vertex_buffer, &quads_vertex_indices_buffer, ); @@ -311,6 +323,7 @@ where alpha_tile_porterduff_program, alpha_tile_overlay_program, alpha_tile_dodgeburn_program, + alpha_tile_softlight_program, alpha_tile_hsl_program, mask_winding_tile_vertex_array, mask_evenodd_tile_vertex_array, @@ -320,6 +333,7 @@ where alpha_tile_porterduff_vertex_array, alpha_tile_overlay_vertex_array, alpha_tile_dodgeburn_vertex_array, + alpha_tile_softlight_vertex_array, alpha_tile_hsl_vertex_array, area_lut_texture, alpha_tile_vertex_buffer, @@ -753,19 +767,27 @@ where let (alpha_tile_program, alpha_tile_vertex_array) = match blend_mode_program { BlendModeProgram::Regular => (&self.alpha_tile_program, &self.alpha_tile_vertex_array), BlendModeProgram::PorterDuff => { - (&self.alpha_tile_porterduff_program.alpha_tile_program, + (&self.alpha_tile_porterduff_program + .alpha_tile_blend_mode_program + .alpha_tile_program, &self.alpha_tile_porterduff_vertex_array) } BlendModeProgram::Overlay => { - (&self.alpha_tile_overlay_program.alpha_tile_program, + (&self.alpha_tile_overlay_program.alpha_tile_blend_mode_program.alpha_tile_program, &self.alpha_tile_overlay_vertex_array) } BlendModeProgram::DodgeBurn => { - (&self.alpha_tile_dodgeburn_program.alpha_tile_program, + (&self.alpha_tile_dodgeburn_program + .alpha_tile_blend_mode_program + .alpha_tile_program, &self.alpha_tile_dodgeburn_vertex_array) } + BlendModeProgram::SoftLight => { + (&self.alpha_tile_softlight_program.alpha_tile_program, + &self.alpha_tile_softlight_vertex_array) + } BlendModeProgram::HSL => { - (&self.alpha_tile_hsl_program.alpha_tile_program, + (&self.alpha_tile_hsl_program.alpha_tile_blend_mode_program.alpha_tile_program, &self.alpha_tile_hsl_vertex_array) } }; @@ -811,6 +833,11 @@ where &mut uniforms, blend_mode); } + BlendModeProgram::SoftLight => { + self.set_uniforms_for_blend_mode(&mut textures, + &mut uniforms, + &self.alpha_tile_softlight_program); + } BlendModeProgram::HSL => { self.set_uniforms_for_hsl_blend_mode(&mut textures, &mut uniforms, blend_mode); } @@ -835,6 +862,16 @@ where self.preserve_draw_framebuffer(); } + fn set_uniforms_for_blend_mode<'a>( + &'a self, + textures: &mut Vec<&'a D::Texture>, + uniforms: &mut Vec<(&'a D::Uniform, UniformData)>, + alpha_tile_blend_mode_program: &'a AlphaTileBlendModeProgram) { + textures.push(self.device.framebuffer_texture(&self.dest_blend_framebuffer)); + uniforms.push((&alpha_tile_blend_mode_program.dest_uniform, + UniformData::TextureUnit(textures.len() as u32 - 1))); + } + fn set_uniforms_for_porter_duff_blend_mode<'a>( &'a self, textures: &mut Vec<&'a D::Texture>, @@ -861,9 +898,10 @@ where uniforms.push((&self.alpha_tile_porterduff_program.dest_factor_uniform, UniformData::Int(dest_factor))); - textures.push(self.device.framebuffer_texture(&self.dest_blend_framebuffer)); - uniforms.push((&self.alpha_tile_porterduff_program.dest_uniform, - UniformData::TextureUnit(textures.len() as u32 - 1))); + self.set_uniforms_for_blend_mode(textures, + uniforms, + &self.alpha_tile_porterduff_program + .alpha_tile_blend_mode_program); } fn set_uniforms_for_overlay_blend_mode<'a>(&'a self, @@ -881,9 +919,10 @@ where uniforms.push((&self.alpha_tile_overlay_program.blend_mode_uniform, UniformData::Int(overlay_blend_mode))); - textures.push(self.device.framebuffer_texture(&self.dest_blend_framebuffer)); - uniforms.push((&self.alpha_tile_overlay_program.dest_uniform, - UniformData::TextureUnit(textures.len() as u32 - 1))); + self.set_uniforms_for_blend_mode(textures, + uniforms, + &self.alpha_tile_overlay_program + .alpha_tile_blend_mode_program); } fn set_uniforms_for_dodge_burn_blend_mode<'a>( @@ -894,9 +933,10 @@ where uniforms.push((&self.alpha_tile_dodgeburn_program.burn_uniform, UniformData::Int(if blend_mode == BlendMode::ColorBurn { 1 } else { 0 }))); - textures.push(self.device.framebuffer_texture(&self.dest_blend_framebuffer)); - uniforms.push((&self.alpha_tile_dodgeburn_program.dest_uniform, - UniformData::TextureUnit(textures.len() as u32 - 1))); + self.set_uniforms_for_blend_mode(textures, + uniforms, + &self.alpha_tile_dodgeburn_program + .alpha_tile_blend_mode_program); } fn set_uniforms_for_hsl_blend_mode<'a>(&'a self, @@ -914,9 +954,10 @@ where uniforms.push((&self.alpha_tile_hsl_program.blend_hsl_uniform, UniformData::IVec3(hsl_terms))); - textures.push(self.device.framebuffer_texture(&self.dest_blend_framebuffer)); - uniforms.push((&self.alpha_tile_hsl_program.dest_uniform, - UniformData::TextureUnit(textures.len() as u32 - 1))); + self.set_uniforms_for_blend_mode(textures, + uniforms, + &self.alpha_tile_hsl_program + .alpha_tile_blend_mode_program); } fn copy_alpha_tiles_to_dest_blend_texture(&mut self, tile_count: u32) { @@ -1544,6 +1585,7 @@ impl BlendModeExt for BlendMode { BlendMode::Overlay | BlendMode::ColorDodge | BlendMode::ColorBurn | + BlendMode::SoftLight | BlendMode::Hue | BlendMode::Saturation | BlendMode::Color | @@ -1561,6 +1603,7 @@ pub(crate) enum BlendModeProgram { PorterDuff, Overlay, DodgeBurn, + SoftLight, HSL, } @@ -1586,6 +1629,7 @@ impl BlendModeProgram { BlendMode::Overlay => BlendModeProgram::Overlay, BlendMode::ColorDodge | BlendMode::ColorBurn => BlendModeProgram::DodgeBurn, + BlendMode::SoftLight => BlendModeProgram::SoftLight, BlendMode::Hue | BlendMode::Saturation | BlendMode::Color | @@ -1599,6 +1643,7 @@ impl BlendModeProgram { BlendModeProgram::PorterDuff | BlendModeProgram::Overlay | BlendModeProgram::DodgeBurn | + BlendModeProgram::SoftLight | BlendModeProgram::HSL => true, } } diff --git a/renderer/src/gpu/shaders.rs b/renderer/src/gpu/shaders.rs index efc1b377..ee6504f8 100644 --- a/renderer/src/gpu/shaders.rs +++ b/renderer/src/gpu/shaders.rs @@ -450,25 +450,39 @@ impl CopyTileProgram where D: Device { } } -pub struct AlphaTilePorterDuffProgram where D: Device { +pub struct AlphaTileBlendModeProgram where D: Device { pub alpha_tile_program: AlphaTileProgram, pub dest_uniform: D::Uniform, +} + +impl AlphaTileBlendModeProgram where D: Device { + pub fn new(device: &D, resources: &dyn ResourceLoader, name: &str) + -> AlphaTileBlendModeProgram { + let alpha_tile_program = + AlphaTileProgram::from_fragment_shader_name(device, resources, name); + let dest_uniform = device.get_uniform(&alpha_tile_program.program, "Dest"); + AlphaTileBlendModeProgram { alpha_tile_program, dest_uniform } + } +} + +pub struct AlphaTilePorterDuffProgram where D: Device { + pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram, pub dest_factor_uniform: D::Uniform, pub src_factor_uniform: D::Uniform, } impl AlphaTilePorterDuffProgram where D: Device { pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTilePorterDuffProgram { - let alpha_tile_program = - AlphaTileProgram::from_fragment_shader_name(device, - resources, - "tile_alpha_porterduff"); - let dest_uniform = device.get_uniform(&alpha_tile_program.program, "Dest"); - let dest_factor_uniform = device.get_uniform(&alpha_tile_program.program, "DestFactor"); - let src_factor_uniform = device.get_uniform(&alpha_tile_program.program, "SrcFactor"); + let alpha_tile_blend_mode_program = + AlphaTileBlendModeProgram::new(device, resources, "tile_alpha_porterduff"); + let dest_factor_uniform = + device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, + "DestFactor"); + let src_factor_uniform = + device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, + "SrcFactor"); AlphaTilePorterDuffProgram { - alpha_tile_program, - dest_uniform, + alpha_tile_blend_mode_program, dest_factor_uniform, src_factor_uniform, } @@ -476,52 +490,50 @@ impl AlphaTilePorterDuffProgram where D: Device { } pub struct AlphaTileHSLProgram where D: Device { - pub alpha_tile_program: AlphaTileProgram, - pub dest_uniform: D::Uniform, + pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram, pub blend_hsl_uniform: D::Uniform, } impl AlphaTileHSLProgram where D: Device { pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileHSLProgram { - let alpha_tile_program = AlphaTileProgram::from_fragment_shader_name(device, - resources, - "tile_alpha_hsl"); - let dest_uniform = device.get_uniform(&alpha_tile_program.program, "Dest"); - let blend_hsl_uniform = device.get_uniform(&alpha_tile_program.program, "BlendHSL"); - AlphaTileHSLProgram { alpha_tile_program, dest_uniform, blend_hsl_uniform } + let alpha_tile_blend_mode_program = + AlphaTileBlendModeProgram::new(device, resources, "tile_alpha_hsl"); + let blend_hsl_uniform = + device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, + "BlendHSL"); + AlphaTileHSLProgram { alpha_tile_blend_mode_program, blend_hsl_uniform } } } pub struct AlphaTileOverlayProgram where D: Device { - pub alpha_tile_program: AlphaTileProgram, - pub dest_uniform: D::Uniform, + pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram, pub blend_mode_uniform: D::Uniform, } impl AlphaTileOverlayProgram where D: Device { pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileOverlayProgram { - let alpha_tile_program = AlphaTileProgram::from_fragment_shader_name(device, - resources, - "tile_alpha_overlay"); - let dest_uniform = device.get_uniform(&alpha_tile_program.program, "Dest"); - let blend_mode_uniform = device.get_uniform(&alpha_tile_program.program, "BlendMode"); - AlphaTileOverlayProgram { alpha_tile_program, dest_uniform, blend_mode_uniform } + let alpha_tile_blend_mode_program = AlphaTileBlendModeProgram::new(device, + resources, + "tile_alpha_overlay"); + let blend_mode_uniform = + device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, + "BlendMode"); + AlphaTileOverlayProgram { alpha_tile_blend_mode_program, blend_mode_uniform } } } pub struct AlphaTileDodgeBurnProgram where D: Device { - pub alpha_tile_program: AlphaTileProgram, - pub dest_uniform: D::Uniform, + pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram, pub burn_uniform: D::Uniform, } impl AlphaTileDodgeBurnProgram where D: Device { pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileDodgeBurnProgram { - let alpha_tile_program = - AlphaTileProgram::from_fragment_shader_name(device, resources, "tile_alpha_dodgeburn"); - let dest_uniform = device.get_uniform(&alpha_tile_program.program, "Dest"); - let burn_uniform = device.get_uniform(&alpha_tile_program.program, "Burn"); - AlphaTileDodgeBurnProgram { alpha_tile_program, dest_uniform, burn_uniform } + let alpha_tile_blend_mode_program = + AlphaTileBlendModeProgram::new(device, resources, "tile_alpha_dodgeburn"); + let burn_uniform = + device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, "Burn"); + AlphaTileDodgeBurnProgram { alpha_tile_blend_mode_program, burn_uniform } } } diff --git a/resources/shaders/gl3/tile_alpha_softlight.fs.glsl b/resources/shaders/gl3/tile_alpha_softlight.fs.glsl new file mode 100644 index 00000000..8299c6ae --- /dev/null +++ b/resources/shaders/gl3/tile_alpha_softlight.fs.glsl @@ -0,0 +1,82 @@ +#version {{version}} +// Automatically generated from files in pathfinder/shaders/. Do not edit! + + + + + + + + + + + + + + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +out vec4 oFragColor; + + + + + + + + + + + + +uniform sampler2D uStencilTexture; +uniform sampler2D uPaintTexture; +uniform sampler2D uDest; +uniform vec2 uFramebufferSize; + +in vec2 vColorTexCoord; +in vec2 vMaskTexCoord; + + +vec4 sampleSrcColor(){ + float coverage = texture(uStencilTexture, vMaskTexCoord). r; + vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage); +} + +vec4 sampleDestColor(){ + vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize; + return texture(uDest, destTexCoord); +} + + +vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){ + return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb + + srcRGBA . a * destRGBA . a * blendedRGB + + (1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb, + 1.0); +} + +vec3 select3(bvec3 cond, vec3 a, vec3 b){ + return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z); +} + + +void main(){ + vec4 srcRGBA = sampleSrcColor(); + vec4 destRGBA = sampleDestColor(); + + + + + vec3 dest = destRGBA . rgb, src = srcRGBA . rgb; + bvec3 destDark = lessThanEqual(dest, vec3(0.25)), srcDark = lessThanEqual(src, vec3(0.5)); + vec3 d = select3(destDark,(dest * 16.0 - 12.0)* dest + 4.0, inversesqrt(dest)); + vec3 x = select3(srcDark, vec3(1.0)- dest, d - 1.0); + vec3 blended = dest *((src * 2.0 - 1.0)* x + 1.0); + + oFragColor = blendColors(destRGBA, srcRGBA, blended); +} + diff --git a/resources/shaders/metal/tile_alpha_softlight.fs.metal b/resources/shaders/metal/tile_alpha_softlight.fs.metal new file mode 100644 index 00000000..9e059bd2 --- /dev/null +++ b/resources/shaders/metal/tile_alpha_softlight.fs.metal @@ -0,0 +1,105 @@ +// Automatically generated from files in pathfinder/shaders/. Do not edit! +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct spvDescriptorSetBuffer0 +{ + texture2d uStencilTexture [[id(0)]]; + sampler uStencilTextureSmplr [[id(1)]]; + texture2d uPaintTexture [[id(2)]]; + sampler uPaintTextureSmplr [[id(3)]]; + constant float2* uFramebufferSize [[id(4)]]; + texture2d uDest [[id(5)]]; + sampler uDestSmplr [[id(6)]]; +}; + +struct main0_out +{ + float4 oFragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vColorTexCoord [[user(locn0)]]; + float2 vMaskTexCoord [[user(locn1)]]; +}; + +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +{ + float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; + float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); + return float4(srcRGBA.xyz, srcRGBA.w * coverage); +} + +float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) +{ + float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize; + return uDest.sample(uDestSmplr, destTexCoord); +} + +float3 select3(thread const bool3& cond, thread const float3& a, thread const float3& b) +{ + float _118; + if (cond.x) + { + _118 = a.x; + } + else + { + _118 = b.x; + } + float _130; + if (cond.y) + { + _130 = a.y; + } + else + { + _130 = b.y; + } + float _142; + if (cond.z) + { + _142 = a.z; + } + else + { + _142 = b.z; + } + return float3(_118, _130, _142); +} + +float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB) +{ + return float4(((srcRGBA.xyz * (srcRGBA.w * (1.0 - destRGBA.w))) + (blendedRGB * (srcRGBA.w * destRGBA.w))) + (destRGBA.xyz * ((1.0 - srcRGBA.w) * destRGBA.w)), 1.0); +} + +fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]]) +{ + main0_out out = {}; + float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); + float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); + float3 dest = destRGBA.xyz; + float3 src = srcRGBA.xyz; + bool3 destDark = dest <= float3(0.25); + bool3 srcDark = src <= float3(0.5); + bool3 param = destDark; + float3 param_1 = (((dest * 16.0) - float3(12.0)) * dest) + float3(4.0); + float3 param_2 = rsqrt(dest); + float3 d = select3(param, param_1, param_2); + bool3 param_3 = srcDark; + float3 param_4 = float3(1.0) - dest; + float3 param_5 = d - float3(1.0); + float3 x = select3(param_3, param_4, param_5); + float3 blended = dest * ((((src * 2.0) - float3(1.0)) * x) + float3(1.0)); + float4 param_6 = destRGBA; + float4 param_7 = srcRGBA; + float3 param_8 = blended; + out.oFragColor = blendColors(param_6, param_7, param_8); + return out; +} + diff --git a/shaders/Makefile b/shaders/Makefile index ce19feba..5e1e2ec9 100644 --- a/shaders/Makefile +++ b/shaders/Makefile @@ -27,6 +27,7 @@ SHADERS=\ tile_alpha_hsl.fs.glsl \ tile_alpha_overlay.fs.glsl \ tile_alpha_porterduff.fs.glsl \ + tile_alpha_softlight.fs.glsl \ tile_copy.fs.glsl \ tile_copy.vs.glsl \ tile_solid.fs.glsl \ diff --git a/shaders/tile_alpha_softlight.fs.glsl b/shaders/tile_alpha_softlight.fs.glsl new file mode 100644 index 00000000..4911986c --- /dev/null +++ b/shaders/tile_alpha_softlight.fs.glsl @@ -0,0 +1,37 @@ +#version 330 + +// pathfinder/shaders/tile_alpha_softlight.fs.glsl +// +// Copyright © 2020 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The soft light blend mode. + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +out vec4 oFragColor; + +#include "tile_alpha_sample.inc.glsl" + +void main() { + vec4 srcRGBA = sampleSrcColor(); + vec4 destRGBA = sampleDestColor(); + + // B(Cb, Cs) = Cb*(1 + (2*Cs - 1)*X) + // where X = if Cs <= 0.5 then 1 - Cb else D - 1 + // and D = if Cb <= 0.25 then (16*Cb - 12)*Cb + 4 else 1/sqrt(Cb) + vec3 dest = destRGBA.rgb, src = srcRGBA.rgb; + bvec3 destDark = lessThanEqual(dest, vec3(0.25)), srcDark = lessThanEqual(src, vec3(0.5)); + vec3 d = select3(destDark, (dest * 16.0 - 12.0) * dest + 4.0, inversesqrt(dest)); + vec3 x = select3(srcDark, vec3(1.0) - dest, d - 1.0); + vec3 blended = dest * ((src * 2.0 - 1.0) * x + 1.0); + + oFragColor = blendColors(destRGBA, srcRGBA, blended); +}