You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

技术求助:用three.js实现Texture map morphing无需自定义着色器

How to Implement Texture Morphing with Fixed UVs in Three.js (No Custom Shaders)

Hey there! Awesome work on that old-school OpenGL+XMLisp implementation—30 lines for texture morphing is seriously impressive. Let’s get you set up with three.js without touching custom shaders, using exactly the approach you described: fixed texture coordinates, only modifying vertex positions to warp the image.

Core Idea

Three.js’s BufferGeometry lets you directly manipulate vertex positions while leaving UV (texture) coordinates untouched. Here’s a step-by-step breakdown:


1. Build a Subdivided Triangle Grid

Start with a PlaneGeometry—it’s perfect because it automatically generates UV coordinates (which we’ll keep fixed) and lets you control how many triangles make up the mesh via subdivision counts:

  • Use the last two parameters of PlaneGeometry to set your grid density (e.g., 32, 32 gives you 33x33 vertices, split into 1024 triangles).
  • Convert it to a non-indexed geometry with toNonIndexed()—this ensures every vertex is independent, so modifying one won’t accidentally warp adjacent faces (critical for precise morphing).

2. Save Original Vertex Positions

You’ll need a baseline to calculate your morph offsets from. Store the original x/y/z values in the geometry’s userData for easy access later:

const planeGeometry = new THREE.PlaneGeometry(2, 2, 32, 32); // Adjust size/subdivisions as needed
const geometry = planeGeometry.toNonIndexed();

// Save original vertex positions to reference later
geometry.userData.originalPositions = new Float32Array(geometry.attributes.position.array);

3. Set Up Texture & Material

Load your target image (Mona Lisa, anatomy illustrations, etc.) and use a simple material that respects the fixed UVs. MeshBasicMaterial works great for static texture display, but you can use MeshStandardMaterial if you need lighting later:

const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('your-image.jpg');
const material = new THREE.MeshBasicMaterial({ 
  map: texture, 
  side: THREE.DoubleSide // So you can see the texture from both sides
});

const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

4. Animate Vertex Morphing

In your animation loop, update the positions of your target vertices using the happiness variable (or any control value you want). The key is to only modify the x/y coordinates (leave z at 0 if you’re working in 2D) and flag the position attribute as updated for three.js to render the changes:

function animate() {
  requestAnimationFrame(animate);

  // Example: Use a sine wave to simulate "happiness" (0-1 range)
  const happiness = Math.sin(Date.now() * 0.001) * 0.5 + 0.5;

  const positions = geometry.attributes.position.array;
  const originalPositions = geometry.userData.originalPositions;

  // Target the two vertices controlled by "happiness"
  // Replace these indices with the actual vertices you want to manipulate
  const targetVertexIndices = [42, 128]; 

  targetVertexIndices.forEach(index => {
    const posIndex = index * 3; // Each vertex has x, y, z (3 array elements)
    // Offset x/y based on happiness, using original position as baseline
    positions[posIndex] = originalPositions[posIndex] + (happiness * 0.2); // X offset
    positions[posIndex + 1] = originalPositions[posIndex + 1] + (happiness * 0.1); // Y offset
  });

  // Tell three.js the position data has changed
  geometry.attributes.position.needsUpdate = true;

  renderer.render(scene, camera);
}
animate();

Key Tips for Your Use Case

  • Vertex Selection: To find the right vertex indices, you can log the geometry.attributes.position.array to inspect coordinates, or generate the grid manually to track specific vertices during creation.
  • Grid Density: Increase the subdivision counts (e.g., 64, 64) for smoother morphing, matching the detail of your original implementation.
  • Anatomical Visualizations: For your Gray’s Anatomy project, just swap the texture and target vertex groups that correspond to the anatomical features you want to warp—this approach works seamlessly for real-time interactive morphing.

内容的提问来源于stack exchange,提问作者Alexander Repenning

火山引擎 最新活动