本文深入解析Phantom.land网站如何利用React Three Fiber、GLSL着色器和GSAP构建动态交互网格与3D面部粒子系统,包含完整的代码实现细节和技术架构设计。
隐形力量:Phantom.land交互式网格与3D面部粒子系统的构建
技术栈选择
项目采用Next.js/React作为基础框架,结合React Three Fiber桥接DOM组件与WebGL上下文。样式系统使用自定义CSS组件和SASS。动画交互选用GSAP,因其支持跨DOM和WebGL组件的统一动画框架,并集成SplitText、CustomEase和ScrollTrigger等插件。
主页网格系统实现
网格架构
网格视图通过Three.js原生对象集成到React Three Fiber场景中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// GridView.tsx
const GridView = () => (
< Canvas >
< ProjectsGrid />
< Postprocessing />
</ Canvas >
);
// ProjectsGrid.tsx
const ProjectsGrid = ({ atlases , tiles }) => {
const { canvas , camera } = useThree ();
const grid = useMemo (() => new Grid ( canvas , camera , atlases , tiles ), []);
return < primitive object = { grid } />;
}
后处理失真效果
通过自定义着色器通道实现动态失真效果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Postprocessing.tsx
const Postprocessing = () => {
const { gl , scene , camera } = useThree ();
const { effectComposer , distortionShader } = useMemo (() => {
const renderPass = new RenderPass ( scene , camera );
const distortionPass = new ShaderPass ( new DistortionShader ());
const composer = new EffectComposer ( gl );
composer . addPass ( renderPass );
composer . addPass ( distortionPass );
composer . addPass ( new OutputPass ());
return { effectComposer , distortionShader };
}, []);
useFrame (() => effectComposer . render (), 1 );
}
GLSL失真着色器
1
2
3
4
5
6
7
8
9
10
11
12
// fragmentShader.glsl
uniform vec2 distortion ;
void main () {
vec2 shiftedUv = 2.0 * ( vUv - 0.5 );
float distanceToCenter = length ( shiftedUv );
shiftedUv *= ( 0.88 + distortion * dot ( shiftedUv ));
vec2 transformedUv = shiftedUv * 0.5 + 0.5 ;
// 渐晕效果
float vignetteIntensity = smoothstep ( 0.8 , vignetteOffset * 0.799 ,
( vignetteDarkness + vignetteOffset ) * distanceToCenter );
gl_FragColor = texture2D ( tDiffuse , transformedUv ) * vignetteIntensity ;
}
交互功能实现
环境鼠标偏移 :
1
2
3
4
getAmbientCursorOffset() {
const uv = this . navigation . pointerUv ;
return uv . subScalar ( 0.5 ). multiplyScalar ( 0.2 );
}
拖拽缩放 :
1
2
3
4
5
6
7
animateCameraZ ( distance : number , duration : number ) {
gsap . to ( this . camera . position , {
z : distance ,
duration ,
ease : CustomEase.create ( 'cameraZoom' , '.23,1,0.32,1' )
});
}
惯性拖拽 :
1
2
3
4
5
6
7
8
update() {
if ( this . isDragAction ) {
this . positionOffset . add ( this . dragAction . clone ());
} else {
this . positionOffset . add ( this . velocity );
}
this . velocity . lerp ( new Vector2 (), 0.1 );
}
3D面部粒子系统
粒子生成架构
使用280×280网格生成78,400个粒子:
1
2
3
4
5
6
7
8
9
10
11
12
13
const FaceParticleSystem = ({ particlesData }) => (
< points >
< bufferGeometry >
< bufferAttribute attach = "attributes-position" args = {[ positions , 3 ]} />
< bufferAttribute attach = "attributes-vRandom" args = {[ randoms , 4 ]} />
</ bufferGeometry >
< shaderMaterial
fragmentShader = { faceFrag }
vertexShader = { faceVert }
uniforms = { uniforms }
/>
</ points >
);
深度驱动粒子定位
1
2
3
4
// vertexShader.glsl
vec3 depthTexture = texture2D ( depthMap , vIndex . xy ). xyz ;
float zDepth = ( 1. - depthValue . z );
pos . z = ( zDepth * 2.0 - 1.0 ) * zScale ;
颜色密度粒子缩放
1
2
3
vec3 colorTexture = texture2D ( colorMap , vIndex . xy ). xyz ;
float density = ( colorTexture . x + colorTexture . y + colorTexture . z ) / 3. ;
float pScale = mix ( pScaleMin , pScaleMax , density );
动态噪声动画
1
pos += curlNoise ( pos * curlFreq1 + time ) * noiseScale * 0.1 ;
面部过渡动画
使用GSAP时间轴控制着色器参数:
1
2
3
timelineRef . current = gsap . timeline ()
. fromTo ( uniforms . transition , { value : 0 }, { value : 1.3 , duration : 1.6 })
. to ( uniforms . zScale , { value : particlesParams.face_scale_z , duration : 1.6 }, 0 );
自定义景深效果
1
2
3
4
5
6
7
vec4 viewPosition = viewMatrix * modelPosition ;
vDistance = abs ( focus + viewPosition . z );
gl_PointSize = pointSize * pScale * vDistance * blur * totalScale ;
// 片段着色器
float alpha = ( 1.04 - clamp ( vDistance * 1.5 , 0.0 , 1.0 ));
gl_FragColor = vec4 ( color , alpha );
技术挑战与解决方案
面部尺度统一 :通过手动校准每个面部的深度缩放、颜色密度平衡和焦点平面优化
性能优化 :使用256×256 WebP纹理(单张<15KB)保持轻量级
视觉一致性 :针对不同拍摄条件定制粒子参数:
1
2
3
4
5
particle_params : {
offset_z : 0 , // 整体Z位置
z_depth_scale : 0 , // 深度图缩放因子
face_size : 0 , // 整体面部缩放
}
结语
该技术方案展示了如何通过精简的WebP纹理、自定义着色器材料和动画系统,将2D肖像转化为交互式3D图形,实现了高性能的视觉体验。
Licensed under CC BY-NC-SA 4.0