UNPKG

@lightningjs/renderer

Version:
143 lines (138 loc) 4.91 kB
/* * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * * Copyright 2023 Comcast Cable Communications Management, LLC. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { getNormalizedRgbaComponents } from '../../../../lib/utils.js'; import { updateFloat32ArrayLength2, updateFloat32ArrayLengthN, } from './EffectUtils.js'; import { ShaderEffect, } from './ShaderEffect.js'; export class RadialGradientEffect extends ShaderEffect { static z$__type__Props; name = 'radialGradient'; static getEffectKey(props) { if (props.colors.value) { return `radialGradient${props.colors.value .length}`; } return `radialGradient${props.colors.length}`; } static resolveDefaults(props) { const colors = props.colors ?? [0xff000000, 0xffffffff]; let stops = props.stops || []; if (stops.length === 0 || stops.length !== colors.length) { const colorsL = colors.length; let i = 0; const tmp = stops; for (; i < colorsL; i++) { if (stops[i]) { tmp[i] = stops[i]; if (stops[i - 1] === undefined && tmp[i - 2] !== undefined) { tmp[i - 1] = tmp[i - 2] + (stops[i] - tmp[i - 2]) / 2; } } else { tmp[i] = i * (1 / (colors.length - 1)); } } stops = tmp; } return { colors, stops, width: props.width ?? 0, height: props.height ?? props.width ?? 0, pivot: props.pivot ?? [0.5, 0.5], }; } static uniforms = { width: { value: 0, method: 'uniform1f', type: 'float', }, height: { value: 0, method: 'uniform1f', type: 'float', }, pivot: { value: [0.5, 0.5], updateProgramValue: updateFloat32ArrayLength2, method: 'uniform2fv', type: 'vec2', }, colors: { value: 0xffffffff, validator: (rgbas) => { return rgbas.reduce((acc, val) => acc.concat(getNormalizedRgbaComponents(val)), []); }, updateProgramValue: updateFloat32ArrayLengthN, size: (props) => props.colors.length, method: 'uniform4fv', type: 'vec4', }, stops: { value: [], size: (props) => props.colors.length, method: 'uniform1fv', type: 'float', }, }; static methods = { getGradientColor: ` float function(float dist) { return clamp(-dist, 0.0, 1.0); } `, }; static ColorLoop = (amount) => { let loop = ''; for (let i = 2; i < amount; i++) { loop += `colorOut = mix(colorOut, colors[${i}], clamp((dist - stops[${i - 1}]) / (stops[${i}] - stops[${i - 1}]), 0.0, 1.0));`; } return loop; }; static onColorize = (props) => { const colors = props.colors.length || 1; return ` vec2 point = v_nodeCoordinate.xy * u_dimensions; vec2 projection = vec2(pivot.x * u_dimensions.x, pivot.y * u_dimensions.y); float dist = length((point - projection) / vec2(width, height)); dist = clamp(dist, 0.0, 1.0); //return early if dist is lower or equal to first stop if(dist <= stops[0]) { return mix(maskColor, colors[0], clamp(colors[0].a, 0.0, 1.0)); } const int amount = ${colors}; const int last = amount - 1; if(dist >= stops[last]) { return mix(maskColor, colors[last], clamp(colors[last].a, 0.0, 1.0)); } for(int i = 0; i < last; i++) { float left = stops[i]; float right = stops[i + 1]; if(dist >= left && dist <= right) { float localDist = smoothstep(left, right, dist); vec4 colorOut = mix(colors[i], colors[i + 1], localDist); return mix(maskColor, colorOut, clamp(colorOut.a, 0.0, 1.0)); } } //final fallback return mix(maskColor, colors[last], clamp(colors[last].a, 0.0, 1.0)); `; }; } //# sourceMappingURL=RadialGradientEffect.js.map