Implement multiply, screen, hard light, and overlay blend modes.
This commit is contained in:
parent
149efeb672
commit
5b228ed825
|
@ -529,8 +529,12 @@ pub enum CompositeOperation {
|
|||
SourceAtop,
|
||||
Xor,
|
||||
Lighter,
|
||||
Lighten,
|
||||
Multiply,
|
||||
Screen,
|
||||
Overlay,
|
||||
Darken,
|
||||
Lighten,
|
||||
HardLight,
|
||||
Hue,
|
||||
Saturation,
|
||||
Color,
|
||||
|
@ -546,8 +550,12 @@ impl CompositeOperation {
|
|||
CompositeOperation::SourceAtop => BlendMode::SrcAtop,
|
||||
CompositeOperation::Xor => BlendMode::Xor,
|
||||
CompositeOperation::Lighter => BlendMode::Lighter,
|
||||
CompositeOperation::Lighten => BlendMode::Lighten,
|
||||
CompositeOperation::Multiply => BlendMode::Multiply,
|
||||
CompositeOperation::Screen => BlendMode::Screen,
|
||||
CompositeOperation::Overlay => BlendMode::Overlay,
|
||||
CompositeOperation::Darken => BlendMode::Darken,
|
||||
CompositeOperation::Lighten => BlendMode::Lighten,
|
||||
CompositeOperation::HardLight => BlendMode::HardLight,
|
||||
CompositeOperation::Hue => BlendMode::Hue,
|
||||
CompositeOperation::Saturation => BlendMode::Saturation,
|
||||
CompositeOperation::Color => BlendMode::Color,
|
||||
|
|
|
@ -64,6 +64,7 @@ pub enum CompositeOp {
|
|||
/// Blend modes that can be applied to individual paths.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum BlendMode {
|
||||
// Supported by GPU blender
|
||||
Clear,
|
||||
SrcOver,
|
||||
DestOver,
|
||||
|
@ -73,6 +74,14 @@ pub enum BlendMode {
|
|||
Lighter,
|
||||
Lighten,
|
||||
Darken,
|
||||
|
||||
// Overlay
|
||||
Multiply,
|
||||
Screen,
|
||||
HardLight,
|
||||
Overlay,
|
||||
|
||||
// HSL
|
||||
Hue,
|
||||
Saturation,
|
||||
Color,
|
||||
|
@ -109,6 +118,10 @@ impl BlendMode {
|
|||
BlendMode::Xor |
|
||||
BlendMode::Lighter |
|
||||
BlendMode::Lighten |
|
||||
BlendMode::Multiply |
|
||||
BlendMode::Screen |
|
||||
BlendMode::HardLight |
|
||||
BlendMode::Overlay |
|
||||
BlendMode::Darken |
|
||||
BlendMode::Hue |
|
||||
BlendMode::Saturation |
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
|
||||
use crate::gpu::debug::DebugUIPresenter;
|
||||
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
||||
use crate::gpu::shaders::{AlphaTileHSLProgram, AlphaTileProgram, AlphaTileVertexArray};
|
||||
use crate::gpu::shaders::{CopyTileProgram, CopyTileVertexArray, FillProgram, FillVertexArray};
|
||||
use crate::gpu::shaders::{FilterBasicProgram, FilterBasicVertexArray, FilterTextProgram};
|
||||
use crate::gpu::shaders::{FilterTextVertexArray, MAX_FILLS_PER_BATCH, MaskTileProgram};
|
||||
use crate::gpu::shaders::{MaskTileVertexArray, ReprojectionProgram, ReprojectionVertexArray};
|
||||
use crate::gpu::shaders::{SolidTileProgram, SolidTileVertexArray};
|
||||
use crate::gpu::shaders::{AlphaTileHSLProgram, AlphaTileOverlayProgram, AlphaTileProgram};
|
||||
use crate::gpu::shaders::{AlphaTileVertexArray, CopyTileProgram, CopyTileVertexArray, FillProgram};
|
||||
use crate::gpu::shaders::{FillVertexArray, FilterBasicProgram, FilterBasicVertexArray};
|
||||
use crate::gpu::shaders::{FilterTextProgram, FilterTextVertexArray, MAX_FILLS_PER_BATCH};
|
||||
use crate::gpu::shaders::{MaskTileProgram, MaskTileVertexArray, ReprojectionProgram};
|
||||
use crate::gpu::shaders::{ReprojectionVertexArray, SolidTileProgram, SolidTileVertexArray};
|
||||
use crate::gpu::shaders::{StencilProgram, StencilVertexArray};
|
||||
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, PaintData, PaintPageContents};
|
||||
use crate::gpu_data::{PaintPageId, RenderCommand, SolidTileVertex};
|
||||
|
@ -50,11 +50,16 @@ pub(crate) const MASK_TILES_DOWN: u32 = 256;
|
|||
const TEXTURE_CACHE_SIZE: usize = 8;
|
||||
|
||||
// FIXME(pcwalton): Shrink this again!
|
||||
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
|
||||
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
|
||||
const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * MASK_TILES_DOWN as i32;
|
||||
|
||||
const BLEND_TERM_DEST: i32 = 0;
|
||||
const BLEND_TERM_SRC: i32 = 1;
|
||||
const BLEND_TERM_DEST: i32 = 0;
|
||||
const BLEND_TERM_SRC: i32 = 1;
|
||||
|
||||
const OVERLAY_BLEND_MODE_MULTIPLY: i32 = 0;
|
||||
const OVERLAY_BLEND_MODE_SCREEN: i32 = 1;
|
||||
const OVERLAY_BLEND_MODE_HARD_LIGHT: i32 = 2;
|
||||
const OVERLAY_BLEND_MODE_OVERLAY: i32 = 3;
|
||||
|
||||
pub struct Renderer<D>
|
||||
where
|
||||
|
@ -72,12 +77,14 @@ where
|
|||
copy_tile_program: CopyTileProgram<D>,
|
||||
solid_tile_program: SolidTileProgram<D>,
|
||||
alpha_tile_program: AlphaTileProgram<D>,
|
||||
alpha_tile_overlay_program: AlphaTileOverlayProgram<D>,
|
||||
alpha_tile_hsl_program: AlphaTileHSLProgram<D>,
|
||||
mask_winding_tile_vertex_array: MaskTileVertexArray<D>,
|
||||
mask_evenodd_tile_vertex_array: MaskTileVertexArray<D>,
|
||||
copy_tile_vertex_array: CopyTileVertexArray<D>,
|
||||
solid_tile_vertex_array: SolidTileVertexArray<D>,
|
||||
alpha_tile_vertex_array: AlphaTileVertexArray<D>,
|
||||
alpha_tile_overlay_vertex_array: AlphaTileVertexArray<D>,
|
||||
alpha_tile_hsl_vertex_array: AlphaTileVertexArray<D>,
|
||||
area_lut_texture: D::Texture,
|
||||
alpha_tile_vertex_buffer: D::Buffer,
|
||||
|
@ -149,6 +156,7 @@ where
|
|||
let copy_tile_program = CopyTileProgram::new(&device, resources);
|
||||
let solid_tile_program = SolidTileProgram::new(&device, resources);
|
||||
let alpha_tile_program = AlphaTileProgram::new(&device, resources);
|
||||
let alpha_tile_overlay_program = AlphaTileOverlayProgram::new(&device, resources);
|
||||
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);
|
||||
|
@ -203,6 +211,12 @@ where
|
|||
&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_vertex_buffer,
|
||||
&quads_vertex_indices_buffer,
|
||||
);
|
||||
let alpha_tile_hsl_vertex_array = AlphaTileVertexArray::new(
|
||||
&device,
|
||||
&alpha_tile_hsl_program.alpha_tile_program,
|
||||
|
@ -270,12 +284,14 @@ where
|
|||
copy_tile_program,
|
||||
solid_tile_program,
|
||||
alpha_tile_program,
|
||||
alpha_tile_overlay_program,
|
||||
alpha_tile_hsl_program,
|
||||
mask_winding_tile_vertex_array,
|
||||
mask_evenodd_tile_vertex_array,
|
||||
copy_tile_vertex_array,
|
||||
solid_tile_vertex_array,
|
||||
alpha_tile_vertex_array,
|
||||
copy_tile_vertex_array,
|
||||
alpha_tile_overlay_vertex_array,
|
||||
alpha_tile_hsl_vertex_array,
|
||||
area_lut_texture,
|
||||
alpha_tile_vertex_buffer,
|
||||
|
@ -708,6 +724,10 @@ 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::Overlay => {
|
||||
(&self.alpha_tile_overlay_program.alpha_tile_program,
|
||||
&self.alpha_tile_overlay_vertex_array)
|
||||
}
|
||||
BlendModeProgram::HSL => {
|
||||
(&self.alpha_tile_hsl_program.alpha_tile_program,
|
||||
&self.alpha_tile_hsl_vertex_array)
|
||||
|
@ -742,6 +762,9 @@ where
|
|||
|
||||
match blend_mode_program {
|
||||
BlendModeProgram::Regular => {}
|
||||
BlendModeProgram::Overlay => {
|
||||
self.set_uniforms_for_overlay_blend_mode(&mut textures, &mut uniforms, blend_mode);
|
||||
}
|
||||
BlendModeProgram::HSL => {
|
||||
self.set_uniforms_for_hsl_blend_mode(&mut textures, &mut uniforms, blend_mode);
|
||||
}
|
||||
|
@ -766,6 +789,26 @@ where
|
|||
self.preserve_draw_framebuffer();
|
||||
}
|
||||
|
||||
fn set_uniforms_for_overlay_blend_mode<'a>(&'a self,
|
||||
textures: &mut Vec<&'a D::Texture>,
|
||||
uniforms: &mut Vec<(&'a D::Uniform, UniformData)>,
|
||||
blend_mode: BlendMode) {
|
||||
let overlay_blend_mode = match blend_mode {
|
||||
BlendMode::Multiply => OVERLAY_BLEND_MODE_MULTIPLY,
|
||||
BlendMode::Screen => OVERLAY_BLEND_MODE_SCREEN,
|
||||
BlendMode::HardLight => OVERLAY_BLEND_MODE_HARD_LIGHT,
|
||||
BlendMode::Overlay => OVERLAY_BLEND_MODE_OVERLAY,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
fn set_uniforms_for_hsl_blend_mode<'a>(&'a self,
|
||||
textures: &mut Vec<&'a D::Texture>,
|
||||
uniforms: &mut Vec<(&'a D::Uniform, UniformData)>,
|
||||
|
@ -778,19 +821,25 @@ where
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
textures.push(self.device.framebuffer_texture(&self.dest_blend_framebuffer));
|
||||
uniforms.push((&self.alpha_tile_hsl_program.dest_uniform, UniformData::TextureUnit(2)));
|
||||
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)));
|
||||
}
|
||||
|
||||
fn copy_alpha_tiles_to_dest_blend_texture(&mut self, tile_count: u32) {
|
||||
let draw_viewport = self.draw_viewport();
|
||||
|
||||
let mut textures = vec![];
|
||||
let mut uniforms = vec![
|
||||
(&self.copy_tile_program.transform_uniform,
|
||||
UniformData::Mat4(self.tile_transform().to_columns())),
|
||||
(&self.copy_tile_program.tile_size_uniform,
|
||||
UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))),
|
||||
(&self.copy_tile_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(draw_viewport.size().to_f32().0)),
|
||||
];
|
||||
|
||||
let draw_framebuffer = match self.draw_render_target() {
|
||||
|
@ -809,7 +858,7 @@ where
|
|||
primitive: Primitive::Triangles,
|
||||
textures: &textures,
|
||||
uniforms: &uniforms,
|
||||
viewport: self.draw_viewport(),
|
||||
viewport: draw_viewport,
|
||||
options: RenderOptions {
|
||||
clear_ops: ClearOps {
|
||||
color: Some(ColorF::transparent_black()),
|
||||
|
@ -1395,6 +1444,10 @@ impl BlendModeExt for BlendMode {
|
|||
op: BlendOp::Min,
|
||||
})
|
||||
}
|
||||
BlendMode::Multiply |
|
||||
BlendMode::Screen |
|
||||
BlendMode::HardLight |
|
||||
BlendMode::Overlay |
|
||||
BlendMode::Hue |
|
||||
BlendMode::Saturation |
|
||||
BlendMode::Color |
|
||||
|
@ -1409,6 +1462,7 @@ impl BlendModeExt for BlendMode {
|
|||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub(crate) enum BlendModeProgram {
|
||||
Regular,
|
||||
Overlay,
|
||||
HSL,
|
||||
}
|
||||
|
||||
|
@ -1424,6 +1478,10 @@ impl BlendModeProgram {
|
|||
BlendMode::Lighter |
|
||||
BlendMode::Lighten |
|
||||
BlendMode::Darken => BlendModeProgram::Regular,
|
||||
BlendMode::Multiply |
|
||||
BlendMode::Screen |
|
||||
BlendMode::HardLight |
|
||||
BlendMode::Overlay => BlendModeProgram::Overlay,
|
||||
BlendMode::Hue |
|
||||
BlendMode::Saturation |
|
||||
BlendMode::Color |
|
||||
|
@ -1434,7 +1492,7 @@ impl BlendModeProgram {
|
|||
pub(crate) fn needs_readable_framebuffer(self) -> bool {
|
||||
match self {
|
||||
BlendModeProgram::Regular => false,
|
||||
BlendModeProgram::HSL => true,
|
||||
BlendModeProgram::Overlay | BlendModeProgram::HSL => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -429,6 +429,7 @@ pub struct CopyTileProgram<D> where D: Device {
|
|||
pub program: D::Program,
|
||||
pub transform_uniform: D::Uniform,
|
||||
pub tile_size_uniform: D::Uniform,
|
||||
pub framebuffer_size_uniform: D::Uniform,
|
||||
pub src_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
|
@ -437,8 +438,15 @@ impl<D> CopyTileProgram<D> where D: Device {
|
|||
let program = device.create_program(resources, "tile_copy");
|
||||
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||
let src_uniform = device.get_uniform(&program, "Src");
|
||||
CopyTileProgram { program, transform_uniform, tile_size_uniform, src_uniform }
|
||||
CopyTileProgram {
|
||||
program,
|
||||
transform_uniform,
|
||||
tile_size_uniform,
|
||||
framebuffer_size_uniform,
|
||||
src_uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,6 +467,23 @@ impl<D> AlphaTileHSLProgram<D> where D: Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileOverlayProgram<D> where D: Device {
|
||||
pub alpha_tile_program: AlphaTileProgram<D>,
|
||||
pub dest_uniform: D::Uniform,
|
||||
pub blend_mode_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileOverlayProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileOverlayProgram<D> {
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilterBasicProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub source_uniform: D::Uniform,
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform int uBlendMode;
|
||||
|
||||
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();
|
||||
|
||||
bool reversed = uBlendMode == 3;
|
||||
vec3 src = reversed ? srcRGBA . rgb : destRGBA . rgb;
|
||||
vec3 dest = reversed ? destRGBA . rgb : srcRGBA . rgb;
|
||||
|
||||
vec3 multiply = src * dest;
|
||||
vec3 blended;
|
||||
if(uBlendMode == 0){
|
||||
blended = multiply;
|
||||
} else {
|
||||
vec3 screen = dest + src - multiply;
|
||||
if(uBlendMode == 1)
|
||||
blended = screen;
|
||||
else
|
||||
blended = select3(lessThanEqual(src, vec3(0.5)), multiply, screen * 2.0 - 1.0);
|
||||
}
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
constant float2* uFramebufferSize [[id(4)]];
|
||||
texture2d<float> uDest [[id(5)]];
|
||||
sampler uDestSmplr [[id(6)]];
|
||||
constant int* uBlendMode [[id(7)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
};
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> 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<float> 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);
|
||||
bool reversed = (*spvDescriptorSet0.uBlendMode) == 3;
|
||||
float3 _167;
|
||||
if (reversed)
|
||||
{
|
||||
_167 = srcRGBA.xyz;
|
||||
}
|
||||
else
|
||||
{
|
||||
_167 = destRGBA.xyz;
|
||||
}
|
||||
float3 src = _167;
|
||||
float3 _178;
|
||||
if (reversed)
|
||||
{
|
||||
_178 = destRGBA.xyz;
|
||||
}
|
||||
else
|
||||
{
|
||||
_178 = srcRGBA.xyz;
|
||||
}
|
||||
float3 dest = _178;
|
||||
float3 multiply = src * dest;
|
||||
float3 blended;
|
||||
if ((*spvDescriptorSet0.uBlendMode) == 0)
|
||||
{
|
||||
blended = multiply;
|
||||
}
|
||||
else
|
||||
{
|
||||
float3 screen = (dest + src) - multiply;
|
||||
if ((*spvDescriptorSet0.uBlendMode) == 1)
|
||||
{
|
||||
blended = screen;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool3 param = src <= float3(0.5);
|
||||
float3 param_1 = multiply;
|
||||
float3 param_2 = (screen * 2.0) - float3(1.0);
|
||||
blended = select3(param, param_1, param_2);
|
||||
}
|
||||
}
|
||||
float4 param_3 = destRGBA;
|
||||
float4 param_4 = srcRGBA;
|
||||
float3 param_5 = blended;
|
||||
out.oFragColor = blendColors(param_3, param_4, param_5);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ SHADERS=\
|
|||
tile_alpha.fs.glsl \
|
||||
tile_alpha.vs.glsl \
|
||||
tile_alpha_hsl.fs.glsl \
|
||||
tile_alpha_overlay.fs.glsl \
|
||||
tile_copy.fs.glsl \
|
||||
tile_copy.vs.glsl \
|
||||
tile_solid.fs.glsl \
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha_overlay.fs.glsl
|
||||
//
|
||||
// Copyright © 2020 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Multiply, screen, overlay, and hard light filters.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#define OVERLAY_BLEND_MODE_MULTIPLY 0
|
||||
#define OVERLAY_BLEND_MODE_SCREEN 1
|
||||
#define OVERLAY_BLEND_MODE_HARD_LIGHT 2
|
||||
#define OVERLAY_BLEND_MODE_OVERLAY 3
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform int uBlendMode;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
bool reversed = uBlendMode == OVERLAY_BLEND_MODE_OVERLAY;
|
||||
vec3 src = reversed ? srcRGBA.rgb : destRGBA.rgb;
|
||||
vec3 dest = reversed ? destRGBA.rgb : srcRGBA.rgb;
|
||||
|
||||
vec3 multiply = src * dest;
|
||||
vec3 blended;
|
||||
if (uBlendMode == OVERLAY_BLEND_MODE_MULTIPLY) {
|
||||
blended = multiply;
|
||||
} else {
|
||||
vec3 screen = dest + src - multiply;
|
||||
if (uBlendMode == OVERLAY_BLEND_MODE_SCREEN)
|
||||
blended = screen;
|
||||
else
|
||||
blended = select3(lessThanEqual(src, vec3(0.5)), multiply, screen * 2.0 - 1.0);
|
||||
}
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
Loading…
Reference in New Issue