🎯 提示词
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 亮度系数进行灰度转换,这种方法符合人眼对不同颜色的敏感度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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);
gl_FragColor = vec4(vec3(grayColor), color.a);
}
在 JavaScript 中通过 uniforms 将纹理传递给着色器。
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.wrapS 和 texture.wrapT 或调整几何体比例 |
🚀 扩展思路
| 变体效果 |
核心改动 |
难度 |
| 复古 sepia 色调 |
修改灰度转换后的颜色映射 |
⭐ |
| 动态对比度调整 |
添加对比度 uniform 参数 |
⭐⭐ |
| 彩色保留效果 |
保留特定颜色通道 |
⭐⭐ |
| 边缘检测叠加 |
添加 Sobel 边缘检测算法 |
⭐⭐⭐ |
本文档由 ThreeLab 编辑整理,如需转载,请注明出处。
💬 评论区
评论功能即将上线,敬请期待!