繁体   English   中英

Three.js / WebGL 如何镜像纹理的一侧

[英]Three.js / WebGL How to mirror one side of a texture

我基本上是在尝试仅用一侧实现万花筒效果,但我正在处理很多点,所以我希望在着色器中发生这种情况。 但是,如果有一个 Threejs 技巧可以镜像一半纹理或 Points object,那就太好了。 我试图应用转换矩阵,但我无法让它工作。

我发现了一个需要使用 EffectComposer 的旧KaleidoShader ,但我想自己手动实现它(没有 EffectComposer),我正在努力做到这一点。 我正在使用 FBO,我尝试在我的模拟和渲染着色器中添加该着色器的代码,但它根本没有任何效果。 我是否必须添加另一个 FBO 纹理,或者是否可以在现有着色器之一中进行这些计算?

视觉参考https://ma-hub.imgix.net/wp-images/2019/01/23205110/premiere-pro-mirror-effect.jpg

我花了这么多时间没有深入了解这一点,希望有人能指出我正确的方向。

谢谢

有一种纹理环绕模式可以进行镜像。

texture.wrapS = texture.wrapT = THREE.MirroredRepeatWrapping

这有帮助吗?

编辑:这是一个在两个轴上显示 mirroredrepeatwrapping 的示例:

https://glitch.com/~three-mirroredrepeatwrapping

我刚刚关注了这篇文章

从该仓库粘贴代码似乎有效

 body { margin: 0; } #c { width: 100vw; height: 100vh; display: block; }
 <canvas id="c"></canvas> <script type="module"> import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js'; import {EffectComposer} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/postprocessing/EffectComposer.js'; import {RenderPass} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/postprocessing/RenderPass.js'; import {ShaderPass} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/postprocessing/ShaderPass.js'; import {GUI} from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js'; function main() { const canvas = document.querySelector('#c'); const renderer = new THREE.WebGLRenderer({canvas}); const fov = 75; const aspect = 2; // the canvas default const near = 0.1; const far = 5; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); camera.position.z = 2; const scene = new THREE.Scene(); { const color = 0xFFFFFF; const intensity = 2; const light = new THREE.DirectionalLight(color, intensity); light.position.set(-1, 2, 4); scene.add(light); } const boxWidth = 1; const boxHeight = 1; const boxDepth = 1; const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth); function makeInstance(geometry, color, x) { const material = new THREE.MeshPhongMaterial({color}); const cube = new THREE.Mesh(geometry, material); scene.add(cube); cube.position.x = x; return cube; } const cubes = [ makeInstance(geometry, 0x44aa88, 0), makeInstance(geometry, 0x8844aa, -2), makeInstance(geometry, 0xaa8844, 2), ]; const composer = new EffectComposer(renderer); composer.addPass(new RenderPass(scene, camera)); // from: // https://github.com/mistic100/three.js-examples/blob/master/LICENSE const kaleidoscopeShader = { uniforms: { "tDiffuse": { value: null }, "sides": { value: 6.0 }, "angle": { value: 0.0 } }, vertexShader: ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); } `, fragmentShader: ` uniform sampler2D tDiffuse; uniform float sides; uniform float angle; varying vec2 vUv; void main() { vec2 p = vUv - 0.5; float r = length(p); float a = atan(py, px) + angle; float tau = 2. * 3.1416; a = mod(a, tau/sides); a = abs(a - tau/sides/2.); p = r * vec2(cos(a), sin(a)); vec4 color = texture2D(tDiffuse, p + 0.5); gl_FragColor = color; } ` }; const kaleidoscopePass = new ShaderPass(kaleidoscopeShader); kaleidoscopePass.renderToScreen = true; composer.addPass(kaleidoscopePass); function resizeRendererToDisplaySize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width.== width || canvas;height.== height, if (needResize) { renderer,setSize(width; height; false); } return needResize. } const gui = new GUI(). gui.add(kaleidoscopePass,uniforms,sides, 'value'. 0; 20).name('sides'). gui.add(kaleidoscopePass,uniforms,angle, 'value'. 0, 6.28. 0;01);name('angle'). let then = 0; function render(now) { now *= 0;001; // convert to seconds const deltaTime = now - then. then = now; if (resizeRendererToDisplaySize(renderer)) { const canvas = renderer.domElement. camera.aspect = canvas;clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(). composer,setSize(canvas.width; canvas.height), } cubes.forEach((cube; ndx) => { const speed = 1 + ndx *;1. const rot = now * speed. cube;rotation.x = rot. cube;rotation;y = rot. }); composer;render(deltaTime); requestAnimationFrame(render); } requestAnimationFrame(render); } main(); </script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM