
Product
PHP and Composer Support Is Now in Beta
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.
@nachi-vfx/post
Advanced tools
Composable screen-space effects for Three.js r185's TSL RenderPipeline. The package provides
shockwave and heat-haze distortion, radial blur, bloom presets, and native-WebGPU weighted blended
OIT without depending on @nachi-vfx/core.
pnpm add @nachi-vfx/post three@0.185.1
# TypeScript projects also need Three's separately published declarations:
pnpm add -D @types/three@0.185.0
The supported peer is exactly three@0.185.1. Post nodes are sensitive to Three's TSL API, so
upgrade Three and this package together.
import { bloomPreset, createPostPipeline, radialBlur, screenDistortion } from '@nachi-vfx/post';
const post = createPostPipeline(renderer, scene, camera, {
distortion: screenDistortion({
shockwaves: [
{
center: [0.5, 0.5],
radius: 0.05,
ringWidth: 0.04,
strength: 0.025,
speed: 0.6,
duration: 0.8,
},
],
heatHaze: [
{
center: [0.5, 0.35],
size: [0.45, 0.3],
strength: 0.008,
},
],
}),
radialBlur: radialBlur({ center: [0.5, 0.5], strength: 0.12, samples: 8 }),
bloom: bloomPreset('soft'),
});
function frame(localTime: number) {
post.controls.setTime(localTime);
post.render(); // use this instead of renderer.render(scene, camera)
}
Before starting the animation loop, await post.prepare({ signal, onProgress }) renders one frame
to the canvas while the loading UI is still covering it. The final composite pipeline cache key
depends on the live output format, sample count, and color space, so an arbitrary offscreen target
cannot prepare it reliably. Pass outputTarget when the live loop presents to a custom target.
Preparation restores the caller's RenderTarget/MRT and does not advance any effect clock.
The default order is distortion -> radialBlur -> bloom. Supply order, for example
['bloom', 'distortion', 'radialBlur'], to choose another permutation. Every configured pass must
appear exactly once.
PostPipelineConfig is revalidated by the public constructor even when direct JavaScript data
bypasses screenDistortion(), radialBlur(), or bloomPreset(). Pass tags/configs, numeric ranges,
source shapes, samples, presets, order arrays, and outputColorTransform fail synchronously before
Three creates a render graph or target.
soft, intense, and cinematic bloom presets wrap Three r185's BloomNode. Overrides can tune
strength, radius, threshold, and internal resolutionScale.
Omitting screenDistortion.time creates a package-owned uniform writable through
post.controls.setTime(). Supplying a number creates a fixed clock, and supplying a TSL node uses
an externally owned clock; the setter rejects both explicit forms. This is the same standalone
uniform/external-node split used by fxMaterial.
Every shockwave and heat-haze field also accepts a number/tuple or a TSL node. Numeric fields become
package-owned uniforms and can be updated with setShockwave() or setHeatHaze(). A node remains
externally owned. Nachi effects should pass their User.* uniform nodes for hit position, radius,
width, strength, and enable state. The gameplay hit already knows those values, so this connection
does not read particle storage back to the CPU. GPU particle readback is deliberately not a hidden
fallback; high-density distortion particles will require a future dedicated distortion buffer.
All coordinates, sizes, radii, widths, strengths, and blur distances are normalized screen UV
units. Shockwaves travel as radius + speed * (time - startTime) and fade over duration.
Heat-haze regions are axis-aligned rectangles with a feathered edge and deterministic procedural
value noise. Its smoothly interpolated lattice produces low-frequency wobble rather than
pixel-to-pixel white noise. Distortion and multi-sample radial-blur UVs use an inset
[0.001, 0.999] clamp.
The pipeline renders into the renderer's currently selected target. Headless WebGPU must select an
offscreen RenderTarget, call post.render(), and use readRenderTargetPixelsAsync(); do not
present the WebGPU canvas. Use outputColorTransform: false when measuring linear pixel thresholds.
Use createWboitPipeline() with a transparent-only scene. Each participating NodeMaterial must
assign createWboitOutput() to material.mrtNode:
const material = new THREE.NodeMaterial();
material.transparent = true;
material.depthWrite = false;
material.mrtNode = createWboitOutput(colorNode, alphaNode);
const oit = createWboitPipeline(renderer, transparentScene, camera, { width, height });
oit.render(); // composites over the renderer's current output target
The accum target is RGBA16F and revealage is R8. Native WebGPU attachment-specific blending is required; WebGL2 is rejected explicitly. WBOIT is order-independent but approximate, so particle bitonic sorting is normally disabled for objects routed through this pipeline. The current pipeline owns a separate depth attachment and cannot import the opaque target's depth, so opaque geometry does not occlude WBOIT fragments yet; keep effects that must disappear behind walls on a sorted alpha path until borrowed-depth ownership is implemented.
FAQs
Composable TSL post effects for Three.js RenderPipeline
The npm package @nachi-vfx/post receives a total of 15 weekly downloads. As such, @nachi-vfx/post popularity was classified as not popular.
We found that @nachi-vfx/post demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.

Product
Socket is bringing experimental protection to Firefox, scanning 97,000+ extensions in Mozilla's official directory for malware and risky updates.

Research
/Security News
Three compromised Rust crates pulled in a malicious dependency that downloaded and executed cross-platform malware during Cargo builds.