3. js / WebGL Как отразить одну сторону текстуры - PullRequest
0 голосов
/ 28 мая 2020

Я в основном пытаюсь достичь эффекта калейдоскопа c только с одной стороны, но я работаю с большим количеством точек, поэтому я бы хотел, чтобы это произошло в шейдере. Однако, если есть трюк Three js, который отражает половину текстуры или объект Points, это было бы здорово. Я попытался применить матрицы трансформации, но не могу заставить его работать.

Я нашел старый KaleidoShader , который требует использования Effect Composer, но я бы хотел реализовать это вручную (без эффекта Composer), и я изо всех сил пытаюсь это сделать. Я использую FBO, и я попытался добавить код этого шейдера как в свои шейдеры моделирования, так и в шейдеры рендеринга, но это не оказало никакого влияния. Нужно ли мне добавить еще одну текстуру FBO или можно выполнить эти вычисления в одном из существующих шейдеров?

Для наглядности https://ma-hub.imgix.net/wp-images/2019/01/23205110/premiere-pro-mirror-effect.jpg

I ' Я потратил так много времени, не разобравшись в этом, надеюсь, кто-нибудь укажет мне верное направление.

Спасибо

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Я только что подписался на эту статью

Кажется, что вставка кода из этого репо работает

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(p.y, p.x) + 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>
1 голос
/ 28 мая 2020

Существует режим обтекания текстурой, который выполняет зеркальное отображение.

texture.wrapS = texture.wrapT = THREE.MirroredRepeatWrapping

Это помогает?

edit: Вот пример, показывающий зеркальное повторение на обеих осях:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...