Three.js如何获取射线与物体交点纹理颜色 系留环项目实践需求
以下是获取射线与地球纹理交点颜色的完整示例代码:
// 提前全局声明需要用到的变量 let earthTextureImage, offscreenCanvas, offscreenCtx, textureWidth, textureHeight; const raycaster = new THREE.Raycaster(); // ========== 初始化部分:只需要执行一次 ========== // 加载地球纹理,纹理加载完成后缓存到离屏canvas方便后续读取像素 const textureLoader = new THREE.TextureLoader(); const earthTexture = textureLoader.load('你的地球表面纹理路径.jpg', (loadedTexture) => { earthTextureImage = loadedTexture.image; textureWidth = earthTextureImage.width; textureHeight = earthTextureImage.height; // 初始化离屏画布 offscreenCanvas = document.createElement('canvas'); offscreenCanvas.width = textureWidth; offscreenCanvas.height = textureHeight; offscreenCtx = offscreenCanvas.getContext('2d'); offscreenCtx.drawImage(earthTextureImage, 0, 0, textureWidth, textureHeight); }); // 初始化地球Mesh,注意SphereGeometry默认自带uv属性,不需要额外配置 const earthGeometry = new THREE.SphereGeometry(6371, 64, 64); // 半径、分段数按你实际场景调整 const earthMaterial = new THREE.MeshStandardMaterial({ map: earthTexture }); const earthMesh = new THREE.Mesh(earthGeometry, earthMaterial); scene.add(earthMesh); // ========== 复用方法:每次需要检测交点颜色时调用 ========== // 参数说明:rayOrigin 射线起点(系留环上的缆线锚点坐标),rayDirection 射线方向(建议指向地心) function getIntersectionColor(rayOrigin, rayDirection) { // 若纹理还未加载完成,直接返回空 if (!offscreenCtx) return null; // 设置射线参数 raycaster.set(rayOrigin, rayDirection); // 仅检测地球Mesh,返回所有交点 const intersects = raycaster.intersectObject(earthMesh); if (intersects.length === 0) return null; // 取第一个正面交点的uv坐标 const hitUv = intersects[0].uv; // 转换uv坐标为纹理像素坐标,需翻转Y轴适配Three.js默认的纹理flipY规则 const pixelX = Math.floor(hitUv.x * textureWidth); const pixelY = Math.floor((1 - hitUv.y) * textureHeight); // 读取对应像素的RGBA值 const pixel = offscreenCtx.getImageData(pixelX, pixelY, 1, 1).data; // 返回归一化的Three.js颜色对象,方便后续和蓝色做阈值比对 return new THREE.Color(pixel[0]/255, pixel[1]/255, pixel[2]/255); } // ========== 调用示例 ========== // 假设系留环上的锚点坐标为(12000, 0, 0),地心为场景原点(0,0,0) const tetherAnchor = new THREE.Vector3(12000, 0, 0); const directionToCore = new THREE.Vector3().subVectors(new THREE.Vector3(0,0,0), tetherAnchor).normalize(); const hitColor = getIntersectionColor(tetherAnchor, directionToCore); if (hitColor) { // 此处可直接执行第二步:将hitColor与海洋蓝色做阈值比对 console.log('交点处纹理颜色:', hitColor); }
注意事项
- 请确保你用来采样颜色的纹理和实际渲染地球的纹理为同一张,避免陆地海洋位置匹配错误
- 如果需要批量检测大量缆线锚点的交点颜色,建议一次性读取整个纹理的像素数据缓存到数组中,避免频繁调用
getImageData产生性能损耗 - 如果你的场景中地球存在自转逻辑,需要同步将自转角度换算为纹理uv的水平偏移,采样时对应调整pixelX的取值,避免位置错位
内容的提问来源于stack exchange,提问作者phil1008
相关产品推荐
相关产品推荐

