UNPKG

@luma.gl/effects

Version:

Post-processing effects for luma.gl

107 lines (95 loc) 3.25 kB
// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import type {ShaderPass} from '@luma.gl/shadertools'; const source = /* wgsl */ `\ uniform inkUniforms { strength: f32, }; @group(0) @binding(1) var<uniform> ink: inkUniforms; fn ink_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) -> vec4f { vec2 dx = vec2(1.0 / texSize.x, 0.0); vec2 dy = vec2(0.0, 1.0 / texSize.y); vec4 color = texture(source, texCoord); float bigTotal = 0.0; float smallTotal = 0.0; vec3 bigAverage = vec3(0.0); vec3 smallAverage = vec3(0.0); for (float x = -2.0; x <= 2.0; x += 1.0) { for (float y = -2.0; y <= 2.0; y += 1.0) { vec3 offsetColor = texture(source, texCoord + dx * x + dy * y).rgb; bigAverage += offsetColor; bigTotal += 1.0; if (abs(x) + abs(y) < 2.0) { smallAverage += offsetColor; smallTotal += 1.0; } } } vec3 edge = max(vec3(0.0), bigAverage / bigTotal - smallAverage / smallTotal); float power = ink.strength * ink.strength * ink.strength * ink.strength * ink.strength; return vec4(color.rgb - dot(edge, edge) * power * 100000.0, color.a); } `; const fs = /* glsl */ `\ uniform inkUniforms { float strength; } ink; vec4 ink_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 dx = vec2(1.0 / texSize.x, 0.0); vec2 dy = vec2(0.0, 1.0 / texSize.y); vec4 color = texture(source, texCoord); float bigTotal = 0.0; float smallTotal = 0.0; vec3 bigAverage = vec3(0.0); vec3 smallAverage = vec3(0.0); for (float x = -2.0; x <= 2.0; x += 1.0) { for (float y = -2.0; y <= 2.0; y += 1.0) { vec3 offsetColor = texture(source, texCoord + dx * x + dy * y).rgb; bigAverage += offsetColor; bigTotal += 1.0; if (abs(x) + abs(y) < 2.0) { smallAverage += offsetColor; smallTotal += 1.0; } } } vec3 edge = max(vec3(0.0), bigAverage / bigTotal - smallAverage / smallTotal); float power = ink.strength * ink.strength * ink.strength * ink.strength * ink.strength; return vec4(color.rgb - dot(edge, edge) * power * 100000.0, color.a); } `; /** * Ink - * Simulates outlining the image in ink by darkening edges stronger than a * certain threshold. The edge detection value is the difference of two * copies of the image, each blurred using a blur of a different radius. */ export type InkProps = { /** The multiplicative scale of the ink edges. * Values in the range 0 to 1 are usually sufficient, where 0 doesn't change the image and 1 adds lots of black edges. * Negative strength values will create white ink edges instead of black ones. */ strength?: number; }; export type InkUniforms = InkProps; /** * Ink - * Simulates outlining the image in ink by darkening edges stronger than a * certain threshold. The edge detection value is the difference of two * copies of the image, each blurred using a blur of a different radius. */ export const ink = { name: 'ink', source, fs, props: {} as InkProps, uniforms: {} as InkUniforms, uniformTypes: { strength: 'f32' }, propTypes: { strength: {value: 0.25, min: 0, softMax: 1} }, passes: [{sampler: true}] } as const satisfies ShaderPass<InkProps, InkProps>;