🎯 提示词

PROMPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
使用 Three.js 实现【图片灰度效果】,具体要求:

【核心特效】
- 基于亮度系数的灰度转换
- 保持原始图片的 alpha 通道

【场景与光照】
- 深灰色背景
- 无需光源(纹理自发光)

【交互与控制】
- OrbitControls 轨道控制器

【技术要求】
- Three.js 最新版本
- ShaderMaterial 自定义着色器
- TextureLoader 加载图片纹理

📖 效果拆解

层次 视觉效果 技术实现
基础 平面几何体 PlaneGeometry
核心特效 灰度转换 加权平均法计算亮度
纹理 图片显示 TextureLoader 加载外部图片

🔧 核心技术点

1. 灰度转换算法

使用标准的 NTSC/PAL 亮度系数进行灰度转换,这种方法符合人眼对不同颜色的敏感度。

GLSL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 定义RGB通道的亮度系数
#define R_LUMINANCE 0.298912
#define G_LUMINANCE 0.586611
#define B_LUMINANCE 0.114478

// 计算灰度的系数向量
const vec3 monochromeScale = vec3(R_LUMINANCE, G_LUMINANCE, B_LUMINANCE);

void main() {
    // 从纹理中获取当前像素的颜色
    vec4 color = texture2D(tDiffuse, vUv);
    
    // 使用点积计算灰度值
    float grayColor = dot(color.rgb, monochromeScale);
    
    // 将灰度值设置为新的颜色,保持alpha通道不变
    gl_FragColor = vec4(vec3(grayColor), color.a);
}

2. Uniforms 纹理传递

在 JavaScript 中通过 uniforms 将纹理传递给着色器。

JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
const uniforms = {
    tDiffuse: { 
        type: 't', 
        value: new THREE.TextureLoader().load('/files/author/AivoGenX.png') 
    }
};

const shaderMaterial = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: vertexShader,
    fragmentShader: fragmentShader
});

💡 调试与优化

问题类型 表现形式 解决方案
纹理显示黑色 图片路径错误或加载失败 检查文件路径,添加 TextureLoader 的 onError 回调
灰度效果不正确 颜色偏色 确认亮度系数值是否正确
性能问题 大尺寸图片帧率下降 使用纹理压缩或降低图片分辨率
纹理拉伸 图片比例失真 设置 texture.wrapStexture.wrapT 或调整几何体比例

🚀 扩展思路

变体效果 核心改动 难度
复古 sepia 色调 修改灰度转换后的颜色映射
动态对比度调整 添加对比度 uniform 参数 ⭐⭐
彩色保留效果 保留特定颜色通道 ⭐⭐
边缘检测叠加 添加 Sobel 边缘检测算法 ⭐⭐⭐

本文档由 ThreeLab 编辑整理,如需转载,请注明出处。