我正在尝试使用 ThreeJs 在三个图像之间创建位移图过渡,但我被卡住了

问题描述 投票:0回答:1

几个月前我开始使用 ThreeJS,这让我转向了 webgl。 我在 youtube 上看了很多课程,但大多数都是针对 3D 构图的。

到目前为止,我对它的工作原理有了基本的了解,但我仍然不擅长某些东西。

事情是这样的。

我试图了解如何从位移纹理中获取数据,即像素位置和值,以便我可以在图像之间切换值并进行过渡。

我正在关注这里的示例,但我正在使用 webpack 和三个 JS,我的海豚在这里不是为了复制,而是为了理解它是如何工作的,我认为这里缺少信息或者我只是无法理解。

无论如何,我在网上找不到太多关于此的信息,但据我所知,我的图像在代码中转换为纹理,所以我应该拥有图像每个像素的值并将这些值转换为UV 坐标并在图像之间切换值以获得我想要的效果。

这是我的存储库的链接

到目前为止我已经有了这个。

这是我加载图像的方法

import * as THREE from 'three';
import { imgTexture1, imgTexture2, imgTexture3 } from './imgLoaderManager.js';

import vertexShader from './glsl/vertex.glsl';
import fragmentShader from './glsl/fragment.glsl';

//
const texturesArr = [imgTexture1, imgTexture2, imgTexture3];



const planeGeometry = new THREE.PlaneBufferGeometry(3, 3);

const planeMaterial = new THREE.ShaderMaterial({
  vertexShader: vertexShader,
  fragmentShader: fragmentShader,
  side: THREE.DoubleSide,
});
planeMaterial.uniforms.uTime = { value: 0 };
planeMaterial.uniforms.uTexture1 = { value: imgTexture1 };
planeMaterial.uniforms.uTexture2 = { value: imgTexture2 };
planeMaterial.uniforms.uTexture3 = { value: imgTexture3 };
planeMaterial.uniforms.uTexture = {
  value: new THREE.TextureLoader().load(texturesArr),
};

console.log(planeMaterial);
console.log(planeGeometry.attributes);
console.log(imgTexture1);
console.log(imgTexture2);
console.log(imgTexture3);

export const plane = new THREE.Mesh(planeGeometry, planeMaterial);

这是我的片段和顶点代码

varying vec2 vUv;
varying vec3 vPosition;
uniform sampler2D uTexture1;
uniform sampler2D uTexture2;
uniform sampler2D uTexture3;

void main() {

    vec3 img1 = texture2D(uTexture1, vUv).xyz;
    vec3 img2 = texture2D(uTexture2, vUv).xyz;
    vec3 img3 = texture2D(uTexture3, vUv).xyz;

    gl_FragColor = vec4(img1 * img2 * img3, 1);
    //gl_FragColor = vec4(vPosition, 1);

}
//////////////////////////////////////////////

varying vec2 vUv;

varying vec3 vPosition;

void main() {
    vPosition = position;
    vUv = uv;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);

}
three.js glsl webgl fragment-shader vertex-shader
1个回答
0
投票

我不太明白您想要实现/理解什么效果...如果是您提供的示例中的效果,您可以使用

mix
函数并插入值来实现。您可以使用纹理代替颜色。

您还打印了坐标和像素值。

<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/[email protected]/build/three.module.js",
      "three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
    }
  }
</script>


<canvas class="webglHH"> </canvas>

<script type="module">
import * as THREE from "three";
import GUI from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
const scene = new THREE.Scene();

const sizes = {
  width: window.innerWidth,
  height: window.innerHeight,
};

const canvas = document.querySelector("canvas.webglHH");

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.z = 3;

const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  antialias: true,
});
renderer.setSize(sizes.width, sizes.height);
renderer.render(scene, camera);

const vertexShader = `
varying vec2 vUv;
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;

const fragmentShader = `
varying vec2 vUv;
uniform float iProgress;

void main() {
    vec3 color1 = vec3(0.556, 0.216, 0.757);
    vec3 color2 = vec3(1.0, 0.941, 0.133);

    // Interpolate between two colors based on iProgress / or if you want textures.
    vec3 mixedColor = mix(color1, color2, iProgress);
    gl_FragColor = vec4(mixedColor, 1);
}
`;

const material = new THREE.ShaderMaterial({
  uniforms: {
    iProgress: { value: 0.0 },
  },
  vertexShader,
  fragmentShader,
});

const geometry = new THREE.PlaneGeometry(3, 3);
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);

const gui = new GUI()
gui.add(material.uniforms.iProgress, 'value', 0.0, 1.0).name('Progress');

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();
canvas.addEventListener('mousemove', (event) => {
  const mouseX = (event.clientX / sizes.width) * 2 - 1;
  const mouseY = -(event.clientY / sizes.height) * 2 + 1;
  const raycaster = new THREE.Raycaster();
  raycaster.setFromCamera({ x: mouseX, y: mouseY }, camera);
  const intersects = raycaster.intersectObject(plane);
  if (intersects.length > 0) {
    const pixelX = Math.floor(intersects[0].uv.x * sizes.width);
    const pixelY = Math.floor((1 - intersects[0].uv.y) * sizes.height);
    console.log(`Pixel Position: (${pixelX}, ${pixelY})`);
    console.log('Color Values:', intersects[0].object.material.uniforms.iProgress.value);
  }
});
function resize() {
  sizes.width = window.innerWidth;
  sizes.height = window.innerHeight;
  camera.aspect = sizes.width / sizes.height;
  camera.updateProjectionMatrix();
  renderer.setSize(sizes.width, sizes.height);
}
window.addEventListener('resize', resize);


</script>

© www.soinside.com 2019 - 2024. All rights reserved.