@aura3d/rendering 1.4.5 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CameraFraming.d.ts +77 -0
- package/dist/CameraFraming.d.ts.map +1 -1
- package/dist/CameraFraming.js +176 -1
- package/dist/CameraFraming.js.map +1 -1
- package/dist/CascadedShadowMaps.d.ts +9 -1
- package/dist/CascadedShadowMaps.d.ts.map +1 -1
- package/dist/CascadedShadowMaps.js +68 -0
- package/dist/CascadedShadowMaps.js.map +1 -1
- package/dist/ClusteredForwardLighting.d.ts +28 -0
- package/dist/ClusteredForwardLighting.d.ts.map +1 -0
- package/dist/ClusteredForwardLighting.js +156 -0
- package/dist/ClusteredForwardLighting.js.map +1 -0
- package/dist/DepthPass.d.ts +14 -1
- package/dist/DepthPass.d.ts.map +1 -1
- package/dist/DepthPass.js +19 -4
- package/dist/DepthPass.js.map +1 -1
- package/dist/EnvironmentMapResources.d.ts +59 -1
- package/dist/EnvironmentMapResources.d.ts.map +1 -1
- package/dist/EnvironmentMapResources.js +140 -100
- package/dist/EnvironmentMapResources.js.map +1 -1
- package/dist/EnvironmentPlatform.d.ts +3 -2
- package/dist/EnvironmentPlatform.d.ts.map +1 -1
- package/dist/EnvironmentPlatform.js +99 -44
- package/dist/EnvironmentPlatform.js.map +1 -1
- package/dist/ForwardPass.d.ts +37 -0
- package/dist/ForwardPass.d.ts.map +1 -1
- package/dist/ForwardPass.js +234 -7
- package/dist/ForwardPass.js.map +1 -1
- package/dist/Geometry.d.ts +19 -0
- package/dist/Geometry.d.ts.map +1 -1
- package/dist/Geometry.js +64 -0
- package/dist/Geometry.js.map +1 -1
- package/dist/IBL.d.ts.map +1 -1
- package/dist/IBL.js +0 -1
- package/dist/IBL.js.map +1 -1
- package/dist/LightCollector.d.ts +5 -1
- package/dist/LightCollector.d.ts.map +1 -1
- package/dist/LightCollector.js +16 -3
- package/dist/LightCollector.js.map +1 -1
- package/dist/LightUniforms.d.ts +26 -1
- package/dist/LightUniforms.d.ts.map +1 -1
- package/dist/LightUniforms.js +140 -8
- package/dist/LightUniforms.js.map +1 -1
- package/dist/LightingRig.d.ts +77 -0
- package/dist/LightingRig.d.ts.map +1 -1
- package/dist/LightingRig.js +100 -11
- package/dist/LightingRig.js.map +1 -1
- package/dist/MeshConsolidation.d.ts +63 -0
- package/dist/MeshConsolidation.d.ts.map +1 -0
- package/dist/MeshConsolidation.js +251 -0
- package/dist/MeshConsolidation.js.map +1 -0
- package/dist/PMREM.d.ts +13 -1
- package/dist/PMREM.d.ts.map +1 -1
- package/dist/PMREM.js +18 -4
- package/dist/PMREM.js.map +1 -1
- package/dist/PostProcessPass.d.ts +24 -2
- package/dist/PostProcessPass.d.ts.map +1 -1
- package/dist/PostProcessPass.js +136 -18
- package/dist/PostProcessPass.js.map +1 -1
- package/dist/PrimitiveSubmissionAudit.d.ts +195 -0
- package/dist/PrimitiveSubmissionAudit.d.ts.map +1 -0
- package/dist/PrimitiveSubmissionAudit.js +280 -0
- package/dist/PrimitiveSubmissionAudit.js.map +1 -0
- package/dist/ProductTurntableFixtures.d.ts.map +1 -1
- package/dist/ProductTurntableFixtures.js +93 -13
- package/dist/ProductTurntableFixtures.js.map +1 -1
- package/dist/ReflectionProbe.d.ts +59 -0
- package/dist/ReflectionProbe.d.ts.map +1 -1
- package/dist/ReflectionProbe.js +224 -0
- package/dist/ReflectionProbe.js.map +1 -1
- package/dist/ReflectionSurfaces.d.ts +4 -2
- package/dist/ReflectionSurfaces.d.ts.map +1 -1
- package/dist/ReflectionSurfaces.js +13 -8
- package/dist/ReflectionSurfaces.js.map +1 -1
- package/dist/RenderBackend.d.ts +1 -1
- package/dist/RenderBackend.d.ts.map +1 -1
- package/dist/RenderBackend.js +5 -1
- package/dist/RenderBackend.js.map +1 -1
- package/dist/RenderDevice.d.ts +13 -2
- package/dist/RenderDevice.d.ts.map +1 -1
- package/dist/RenderDevice.js +5 -2
- package/dist/RenderDevice.js.map +1 -1
- package/dist/Renderer.d.ts +66 -3
- package/dist/Renderer.d.ts.map +1 -1
- package/dist/Renderer.js +417 -64
- package/dist/Renderer.js.map +1 -1
- package/dist/RendererPostprocessPlan.d.ts +10 -3
- package/dist/RendererPostprocessPlan.d.ts.map +1 -1
- package/dist/RendererPostprocessPlan.js +25 -5
- package/dist/RendererPostprocessPlan.js.map +1 -1
- package/dist/RendererVisualPipelineReport.d.ts +3 -2
- package/dist/RendererVisualPipelineReport.d.ts.map +1 -1
- package/dist/RendererVisualPipelineReport.js +2 -0
- package/dist/RendererVisualPipelineReport.js.map +1 -1
- package/dist/ScreenSpaceLineMaterial.d.ts +34 -0
- package/dist/ScreenSpaceLineMaterial.d.ts.map +1 -0
- package/dist/ScreenSpaceLineMaterial.js +93 -0
- package/dist/ScreenSpaceLineMaterial.js.map +1 -0
- package/dist/ShaderChunks.d.ts +7 -0
- package/dist/ShaderChunks.d.ts.map +1 -1
- package/dist/ShaderChunks.js +137 -0
- package/dist/ShaderChunks.js.map +1 -1
- package/dist/ShaderLibrary.d.ts +17 -0
- package/dist/ShaderLibrary.d.ts.map +1 -1
- package/dist/ShaderLibrary.js +940 -98
- package/dist/ShaderLibrary.js.map +1 -1
- package/dist/ShadowPass.d.ts +10 -0
- package/dist/ShadowPass.d.ts.map +1 -1
- package/dist/ShadowPass.js +8 -1
- package/dist/ShadowPass.js.map +1 -1
- package/dist/SkinnedLitMaterial.d.ts +6 -0
- package/dist/SkinnedLitMaterial.d.ts.map +1 -1
- package/dist/SkinnedLitMaterial.js +22 -8
- package/dist/SkinnedLitMaterial.js.map +1 -1
- package/dist/SkinnedUnlitMaterial.d.ts +8 -0
- package/dist/SkinnedUnlitMaterial.d.ts.map +1 -1
- package/dist/SkinnedUnlitMaterial.js +26 -9
- package/dist/SkinnedUnlitMaterial.js.map +1 -1
- package/dist/SpecularPrefilter.d.ts +42 -0
- package/dist/SpecularPrefilter.d.ts.map +1 -0
- package/dist/SpecularPrefilter.js +480 -0
- package/dist/SpecularPrefilter.js.map +1 -0
- package/dist/TerrainFixtures.d.ts +24 -0
- package/dist/TerrainFixtures.d.ts.map +1 -1
- package/dist/TerrainFixtures.js +96 -0
- package/dist/TerrainFixtures.js.map +1 -1
- package/dist/Texture.d.ts +7 -0
- package/dist/Texture.d.ts.map +1 -1
- package/dist/Texture.js +9 -0
- package/dist/Texture.js.map +1 -1
- package/dist/VertexFormat.d.ts +34 -1
- package/dist/VertexFormat.d.ts.map +1 -1
- package/dist/VertexFormat.js +61 -0
- package/dist/VertexFormat.js.map +1 -1
- package/dist/WebGL2Device.d.ts +48 -0
- package/dist/WebGL2Device.d.ts.map +1 -1
- package/dist/WebGL2Device.js +1298 -44
- package/dist/WebGL2Device.js.map +1 -1
- package/dist/WebGPUDevice.d.ts +7 -2
- package/dist/WebGPUDevice.d.ts.map +1 -1
- package/dist/WebGPUDevice.js +111 -17
- package/dist/WebGPUDevice.js.map +1 -1
- package/dist/WebGPUSkinningLimits.d.ts +14 -0
- package/dist/WebGPUSkinningLimits.d.ts.map +1 -0
- package/dist/WebGPUSkinningLimits.js +14 -0
- package/dist/WebGPUSkinningLimits.js.map +1 -0
- package/dist/cartoon/CartoonMaterialStyle.d.ts +19 -0
- package/dist/cartoon/CartoonMaterialStyle.d.ts.map +1 -0
- package/dist/cartoon/CartoonMaterialStyle.js +13 -0
- package/dist/cartoon/CartoonMaterialStyle.js.map +1 -0
- package/dist/cartoon/CartoonRenderPreset.d.ts +36 -0
- package/dist/cartoon/CartoonRenderPreset.d.ts.map +1 -0
- package/dist/cartoon/CartoonRenderPreset.js +23 -0
- package/dist/cartoon/CartoonRenderPreset.js.map +1 -0
- package/dist/cartoon/CartoonToonMaterial.d.ts +130 -0
- package/dist/cartoon/CartoonToonMaterial.d.ts.map +1 -0
- package/dist/cartoon/CartoonToonMaterial.js +303 -0
- package/dist/cartoon/CartoonToonMaterial.js.map +1 -0
- package/dist/cartoon/CartoonVisualQuality.d.ts +28 -0
- package/dist/cartoon/CartoonVisualQuality.d.ts.map +1 -0
- package/dist/cartoon/CartoonVisualQuality.js +39 -0
- package/dist/cartoon/CartoonVisualQuality.js.map +1 -0
- package/dist/cartoon/applyCartoonRenderPreset.d.ts +79 -0
- package/dist/cartoon/applyCartoonRenderPreset.d.ts.map +1 -0
- package/dist/cartoon/applyCartoonRenderPreset.js +88 -0
- package/dist/cartoon/applyCartoonRenderPreset.js.map +1 -0
- package/dist/cartoon/index.d.ts +6 -0
- package/dist/cartoon/index.d.ts.map +1 -0
- package/dist/cartoon/index.js +6 -0
- package/dist/cartoon/index.js.map +1 -0
- package/dist/index.d.ts +29 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -10
- package/dist/index.js.map +1 -1
- package/dist/postprocess/NativeLdrEffectLuts.d.ts +93 -0
- package/dist/postprocess/NativeLdrEffectLuts.d.ts.map +1 -0
- package/dist/postprocess/NativeLdrEffectLuts.js +202 -0
- package/dist/postprocess/NativeLdrEffectLuts.js.map +1 -0
- package/dist/production-runtime/PBRHDRPipeline.d.ts.map +1 -1
- package/dist/production-runtime/PBRHDRPipeline.js +3 -0
- package/dist/production-runtime/PBRHDRPipeline.js.map +1 -1
- package/dist/production-runtime/ProductionRendererTypes.d.ts +1 -0
- package/dist/production-runtime/ProductionRendererTypes.d.ts.map +1 -1
- package/dist/production-runtime/ProductionRendererTypes.js.map +1 -1
- package/dist/production-runtime/ProductionWebGL2Renderer.d.ts.map +1 -1
- package/dist/production-runtime/ProductionWebGL2Renderer.js +5 -3
- package/dist/production-runtime/ProductionWebGL2Renderer.js.map +1 -1
- package/dist/production-runtime/ProductionWebGPURenderer.d.ts.map +1 -1
- package/dist/production-runtime/ProductionWebGPURenderer.js +9 -5
- package/dist/production-runtime/ProductionWebGPURenderer.js.map +1 -1
- package/dist/production-runtime/TransmissionBackdropCapture.d.ts +5 -0
- package/dist/production-runtime/TransmissionBackdropCapture.d.ts.map +1 -1
- package/dist/production-runtime/TransmissionBackdropCapture.js +40 -0
- package/dist/production-runtime/TransmissionBackdropCapture.js.map +1 -1
- package/dist/production-runtime/environment/HDRLoader.d.ts +6 -0
- package/dist/production-runtime/environment/HDRLoader.d.ts.map +1 -1
- package/dist/production-runtime/environment/HDRLoader.js +19 -0
- package/dist/production-runtime/environment/HDRLoader.js.map +1 -1
- package/dist/production-runtime/index.d.ts +3 -1
- package/dist/production-runtime/index.d.ts.map +1 -1
- package/dist/production-runtime/index.js +1 -0
- package/dist/production-runtime/index.js.map +1 -1
- package/package.json +3 -3
package/dist/PostProcessPass.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseRenderPass } from "./RenderPass.js";
|
|
2
2
|
import { RenderDeviceError } from "./RenderDevice.js";
|
|
3
|
+
import { OUTLINE_LUMA_SCALE, createOutlineGradientBound } from "./postprocess/NativeLdrEffectLuts.js";
|
|
3
4
|
export class ToneMappingPass extends BaseRenderPass {
|
|
4
5
|
options;
|
|
5
6
|
exposure;
|
|
@@ -511,16 +512,20 @@ export function outlinePixels(pixels, width, height, options = {}) {
|
|
|
511
512
|
validateRange(opacity, 0, 1, "Outline opacity");
|
|
512
513
|
validateOutlineColor(color);
|
|
513
514
|
const edgeMask = new Uint8Array(width * height);
|
|
514
|
-
|
|
515
|
+
const gradientBound = createOutlineGradientBound(threshold).numberValue;
|
|
516
|
+
let maxGradientNumerator = 0;
|
|
515
517
|
for (let y = 0; y < height; y += 1) {
|
|
516
518
|
for (let x = 0; x < width; x += 1) {
|
|
517
|
-
const
|
|
518
|
-
|
|
519
|
-
if (
|
|
519
|
+
const { gx, gy } = sobelLumaNumeratorGradient(pixels, width, height, x, y);
|
|
520
|
+
const squared = gx * gx + gy * gy;
|
|
521
|
+
if (squared > maxGradientNumerator)
|
|
522
|
+
maxGradientNumerator = squared;
|
|
523
|
+
if (outlineEdgeExceedsBound(gx, gy, gradientBound)) {
|
|
520
524
|
edgeMask[y * width + x] = 255;
|
|
521
525
|
}
|
|
522
526
|
}
|
|
523
527
|
}
|
|
528
|
+
const maxGradient = Math.sqrt(maxGradientNumerator) / OUTLINE_LUMA_SCALE;
|
|
524
529
|
const outlineMask = dilateMask(edgeMask, width, height, outlineWidth);
|
|
525
530
|
const output = new Uint8Array(pixels);
|
|
526
531
|
let outlinedPixels = 0;
|
|
@@ -636,6 +641,80 @@ export function depthOfFieldPixels(pixels, width, height, options) {
|
|
|
636
641
|
}
|
|
637
642
|
return { width, height, pixels: output, blurredPixels, maxBlurRadius: maxRadius, focusDepth, focusRange };
|
|
638
643
|
}
|
|
644
|
+
export function volumetricLightPixels(pixels, width, height, options = {}) {
|
|
645
|
+
validatePixelBuffer(pixels, width, height, "Volumetric light");
|
|
646
|
+
const depth = requireDepthTextureBinding(options.depth, "Volumetric light");
|
|
647
|
+
if (depth.width !== width || depth.height !== height) {
|
|
648
|
+
throw new Error("Volumetric light depth texture dimensions must match source pixels.");
|
|
649
|
+
}
|
|
650
|
+
const lightPosition = options.lightPosition ?? [0.5, 0.18];
|
|
651
|
+
if (lightPosition.length !== 2 || !lightPosition.every((value) => Number.isFinite(value) && value >= 0 && value <= 1)) {
|
|
652
|
+
throw new RangeError("Volumetric light position must contain two finite normalized coordinates.");
|
|
653
|
+
}
|
|
654
|
+
const color = options.color ?? [1, 0.88, 0.62];
|
|
655
|
+
if (color.length !== 3 || !color.every((value) => Number.isFinite(value) && value >= 0 && value <= 1)) {
|
|
656
|
+
throw new RangeError("Volumetric light color must contain three finite values within [0, 1].");
|
|
657
|
+
}
|
|
658
|
+
const density = numberInRange(options.density ?? 0.9, 0.01, 2, "Volumetric light density");
|
|
659
|
+
const decay = numberInRange(options.decay ?? 0.96, 0, 1, "Volumetric light decay");
|
|
660
|
+
const weight = numberInRange(options.weight ?? 0.18, 0, 2, "Volumetric light weight");
|
|
661
|
+
const exposure = numberInRange(options.exposure ?? 0.72, 0, 4, "Volumetric light exposure");
|
|
662
|
+
const samples = integerNumberInRange(options.samples ?? 32, 4, 128, "Volumetric light samples");
|
|
663
|
+
const occlusionThreshold = numberInRange(options.occlusionThreshold ?? 0.985, 0, 1, "Volumetric light occlusionThreshold");
|
|
664
|
+
const output = new Uint8Array(pixels);
|
|
665
|
+
const lightX = lightPosition[0] * (width - 1);
|
|
666
|
+
const lightY = lightPosition[1] * (height - 1);
|
|
667
|
+
let changedPixels = 0;
|
|
668
|
+
let occludedSamples = 0;
|
|
669
|
+
let maxScattering = 0;
|
|
670
|
+
for (let y = 0; y < height; y += 1) {
|
|
671
|
+
for (let x = 0; x < width; x += 1) {
|
|
672
|
+
const deltaX = ((lightX - x) / samples) * density;
|
|
673
|
+
const deltaY = ((lightY - y) / samples) * density;
|
|
674
|
+
let sampleX = x;
|
|
675
|
+
let sampleY = y;
|
|
676
|
+
let illuminationDecay = 1;
|
|
677
|
+
let scattering = 0;
|
|
678
|
+
for (let sample = 0; sample < samples; sample += 1) {
|
|
679
|
+
sampleX += deltaX;
|
|
680
|
+
sampleY += deltaY;
|
|
681
|
+
const sx = clampInt(Math.round(sampleX), 0, width - 1);
|
|
682
|
+
const sy = clampInt(Math.round(sampleY), 0, height - 1);
|
|
683
|
+
const offset = (sy * width + sx) * 4;
|
|
684
|
+
const luminance = ((pixels[offset] ?? 0) * 0.2126 + (pixels[offset + 1] ?? 0) * 0.7152 + (pixels[offset + 2] ?? 0) * 0.0722) / 255;
|
|
685
|
+
const source = Math.max(0, luminance - 0.42) / 0.58;
|
|
686
|
+
const sampleDepth = depthAt(depth, sx, sy);
|
|
687
|
+
const visible = sampleDepth >= occlusionThreshold || source > 0.05 ? 1 : 0;
|
|
688
|
+
if (visible === 0)
|
|
689
|
+
occludedSamples += 1;
|
|
690
|
+
scattering += source * visible * illuminationDecay * weight;
|
|
691
|
+
illuminationDecay *= decay;
|
|
692
|
+
}
|
|
693
|
+
const boost = scattering * exposure;
|
|
694
|
+
maxScattering = Math.max(maxScattering, boost);
|
|
695
|
+
const offset = (y * width + x) * 4;
|
|
696
|
+
const beforeR = pixels[offset] ?? 0;
|
|
697
|
+
const beforeG = pixels[offset + 1] ?? 0;
|
|
698
|
+
const beforeB = pixels[offset + 2] ?? 0;
|
|
699
|
+
output[offset] = clampByte(beforeR + color[0] * boost * 255);
|
|
700
|
+
output[offset + 1] = clampByte(beforeG + color[1] * boost * 255);
|
|
701
|
+
output[offset + 2] = clampByte(beforeB + color[2] * boost * 255);
|
|
702
|
+
if (output[offset] !== beforeR || output[offset + 1] !== beforeG || output[offset + 2] !== beforeB) {
|
|
703
|
+
changedPixels += 1;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return {
|
|
708
|
+
width,
|
|
709
|
+
height,
|
|
710
|
+
pixels: output,
|
|
711
|
+
changedPixels,
|
|
712
|
+
occludedSamples,
|
|
713
|
+
maxScattering: Number(maxScattering.toFixed(5)),
|
|
714
|
+
sampleCount: samples,
|
|
715
|
+
method: "depth-aware-radial-participating-media"
|
|
716
|
+
};
|
|
717
|
+
}
|
|
639
718
|
export function motionBlurPixels(pixels, width, height, options) {
|
|
640
719
|
validatePixelBuffer(pixels, width, height, "Motion blur");
|
|
641
720
|
const samples = options.samples ?? 5;
|
|
@@ -1253,6 +1332,7 @@ export function fxaaPixels(pixels, width, height, options = {}) {
|
|
|
1253
1332
|
}
|
|
1254
1333
|
export function fusedLdrPostprocessPixels(pixels, width, height, passes, options = {}) {
|
|
1255
1334
|
validatePixelBuffer(pixels, width, height, "Fused LDR postprocess");
|
|
1335
|
+
const bloom = passes.find((pass) => pass.name === "bloom");
|
|
1256
1336
|
const toneMapping = passes.find((pass) => pass.name === "tone-mapping");
|
|
1257
1337
|
const colorGrade = passes.find((pass) => pass.name === "color-grade");
|
|
1258
1338
|
const fxaa = passes.find((pass) => pass.name === "fxaa");
|
|
@@ -1264,7 +1344,9 @@ export function fusedLdrPostprocessPixels(pixels, width, height, passes, options
|
|
|
1264
1344
|
: undefined;
|
|
1265
1345
|
const colorGradeSettings = colorGrade ? normalizeColorGradeOptions(colorGrade.options) : undefined;
|
|
1266
1346
|
const byteLength = pixels.byteLength;
|
|
1267
|
-
let current =
|
|
1347
|
+
let current = bloom
|
|
1348
|
+
? bloomPixels(pixels, width, height, bloom.options).pixels
|
|
1349
|
+
: pixels;
|
|
1268
1350
|
if (toneMappingLookup || colorGradeSettings) {
|
|
1269
1351
|
const target = options.mutateInput
|
|
1270
1352
|
? pixels
|
|
@@ -1272,7 +1354,7 @@ export function fusedLdrPostprocessPixels(pixels, width, height, passes, options
|
|
|
1272
1354
|
const vignetteFactors = colorGradeSettings && colorGradeSettings.vignette > 0
|
|
1273
1355
|
? getVignetteFactors(width, height, colorGradeSettings.vignette, options.scratch)
|
|
1274
1356
|
: undefined;
|
|
1275
|
-
applyToneMappingAndColorGrade(
|
|
1357
|
+
applyToneMappingAndColorGrade(current, target, width, height, toneMappingLookup, colorGradeSettings, vignetteFactors);
|
|
1276
1358
|
current = target;
|
|
1277
1359
|
}
|
|
1278
1360
|
if (colorGradeSettings && colorGradeSettings.sharpening > 0) {
|
|
@@ -1536,18 +1618,37 @@ function validateOutlineColor(color) {
|
|
|
1536
1618
|
}
|
|
1537
1619
|
}
|
|
1538
1620
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
const
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1621
|
+
/**
|
|
1622
|
+
* Sobel response of the integer luma numerator `2126 * r + 7152 * g + 722 * b`.
|
|
1623
|
+
*
|
|
1624
|
+
* This is the same operator as {@link sobelLumaGradient} scaled by `OUTLINE_LUMA_SCALE`, but every
|
|
1625
|
+
* intermediate is an exact integer: each numerator is at most `2550000`, so a response is at most
|
|
1626
|
+
* `4 * 2550000` and the squared magnitude used by {@link outlineEdgeExceedsBound} stays below 2^48,
|
|
1627
|
+
* well inside the range where float64 represents integers exactly.
|
|
1628
|
+
*/
|
|
1629
|
+
function sobelLumaNumeratorGradient(pixels, width, height, x, y) {
|
|
1630
|
+
const nw = lumaNumeratorAt(pixels, width, height, x - 1, y - 1);
|
|
1631
|
+
const n = lumaNumeratorAt(pixels, width, height, x, y - 1);
|
|
1632
|
+
const ne = lumaNumeratorAt(pixels, width, height, x + 1, y - 1);
|
|
1633
|
+
const w = lumaNumeratorAt(pixels, width, height, x - 1, y);
|
|
1634
|
+
const e = lumaNumeratorAt(pixels, width, height, x + 1, y);
|
|
1635
|
+
const sw = lumaNumeratorAt(pixels, width, height, x - 1, y + 1);
|
|
1636
|
+
const s = lumaNumeratorAt(pixels, width, height, x, y + 1);
|
|
1637
|
+
const se = lumaNumeratorAt(pixels, width, height, x + 1, y + 1);
|
|
1638
|
+
return {
|
|
1639
|
+
gx: -nw - 2 * w - sw + ne + 2 * e + se,
|
|
1640
|
+
gy: -nw - 2 * n - ne + sw + 2 * s + se
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Exact outline edge predicate shared by the CPU kernel and the WebGL2 shader.
|
|
1645
|
+
*
|
|
1646
|
+
* Equivalent to `hypot(gx, gy) >= threshold` on the real numbers, but decided with integers so
|
|
1647
|
+
* that it never depends on float rounding. `bound` comes from {@link createOutlineGradientBound},
|
|
1648
|
+
* which pre-squares the threshold as an exact rational and rounds up.
|
|
1649
|
+
*/
|
|
1650
|
+
function outlineEdgeExceedsBound(gx, gy, bound) {
|
|
1651
|
+
return gx * gx + gy * gy >= bound;
|
|
1551
1652
|
}
|
|
1552
1653
|
function dilateMask(mask, width, height, radius) {
|
|
1553
1654
|
const output = new Uint8Array(mask.length);
|
|
@@ -1793,6 +1894,16 @@ function validateRange(value, min, max, label) {
|
|
|
1793
1894
|
throw new Error(`${label} must be finite and within [${min}, ${max}].`);
|
|
1794
1895
|
}
|
|
1795
1896
|
}
|
|
1897
|
+
function numberInRange(value, min, max, label) {
|
|
1898
|
+
validateRange(value, min, max, label);
|
|
1899
|
+
return value;
|
|
1900
|
+
}
|
|
1901
|
+
function integerNumberInRange(value, min, max, label) {
|
|
1902
|
+
validateRange(value, min, max, label);
|
|
1903
|
+
if (!Number.isInteger(value))
|
|
1904
|
+
throw new Error(`${label} must be an integer.`);
|
|
1905
|
+
return value;
|
|
1906
|
+
}
|
|
1796
1907
|
function clampByte(value) {
|
|
1797
1908
|
return Math.round(Math.max(0, Math.min(255, value)));
|
|
1798
1909
|
}
|
|
@@ -1805,6 +1916,13 @@ function lumaAt(pixels, width, height, x, y) {
|
|
|
1805
1916
|
const index = (sampleY * width + sampleX) * 4;
|
|
1806
1917
|
return (0.2126 * pixels[index] + 0.7152 * pixels[index + 1] + 0.0722 * pixels[index + 2]) / 255;
|
|
1807
1918
|
}
|
|
1919
|
+
/** Integer luma numerator at a clamped coordinate, matching the outline shader exactly. */
|
|
1920
|
+
function lumaNumeratorAt(pixels, width, height, x, y) {
|
|
1921
|
+
const sampleX = clampInt(x, 0, width - 1);
|
|
1922
|
+
const sampleY = clampInt(y, 0, height - 1);
|
|
1923
|
+
const index = (sampleY * width + sampleX) * 4;
|
|
1924
|
+
return 2126 * pixels[index] + 7152 * pixels[index + 1] + 722 * pixels[index + 2];
|
|
1925
|
+
}
|
|
1808
1926
|
function channelAt(pixels, width, height, x, y, channel) {
|
|
1809
1927
|
const sampleX = clampInt(x, 0, width - 1);
|
|
1810
1928
|
const sampleY = clampInt(y, 0, height - 1);
|