kwicherbelliaken / bad-reviews-make-good-movies

0 stars 0 forks source link

[FEATURE]: add support for ThreeJS #8

Closed slackermorris closed 1 year ago

slackermorris commented 1 year ago

https://www.blackspike.com/blog/why-we-chose-astro-over-nuxt/

slackermorris commented 1 year ago

In adding support for ThreeJS I also realise that it would make sense to review the best practices associated with Astro.

slackermorris commented 1 year ago

This is precisely what I want to do for the landing page.

I'm going to have to properly extract this somehow. And I should reach out to Ksenia and thank them.

slackermorris commented 1 year ago

I would really like to make use of this animated SVG logo as well:

And this font:

And emojis:

slackermorris commented 1 year ago

DON'T FORGET ABOUT PARTYTOWN.

slackermorris commented 1 year ago

I should probably read this before sinking my teeth in too much:

This would be good to read, it is a comparison between the different frameworks:

slackermorris commented 1 year ago

SOME CONFUSION ABOUT BUNDLERS

I am really fucking confused.

Astro offers support for Vite plugins to manage advanced configuration options that Astro currently does not support: https://docs.astro.build/en/reference/configuration-reference/#vite.

Astro uses Turbo under the hood: a webpack successor.

Vite uses Rollup as its bundler under the hood. Vite is part bundler part dev server.

So, why are we using Vite instead of just grabbing Rollup?

Because they are obviously different. Turbopack and Vite.

This helped me understand. A little.

SO, DOES ASTRO USE TURBOPACK OR VITE?

Because this would decide what would be best used in terms of plugin support. So strange.

slackermorris commented 1 year ago

☝️ adding vite or rollup plugins:

slackermorris commented 1 year ago

Fuck it. I should just install the dep and not worry about it. Yeah, I've just installed vite-plugin-glsl.

slackermorris commented 1 year ago

I think as I am implementing the flower effect I can clean up the way threeJS has been implemented.

slackermorris commented 1 year ago

This is the JS implementation of the ThreeJS Flower Animation:


let pointer = {
  x: 0.65,
  y: 0.3,
  clicked: true,
};

// only for codepen preview
let isStart = true;

let isRendering = true;

let renderer, shaderScene, mainScene, sceneTest, renderTargets, camera, clock;
let basicMaterial, shaderMaterial;

const backgroundColor = new THREE.Color(0xffffff);

initScene();

updateSize();

window.addEventListener("resize", updateSize);

function handleClickOrTouch(e) {
  e.preventDefault(); // Prevent default touch behavior

  let clientX, clientY;

  if (e.type === "click") {
    clientX = e.clientX;
    clientY = e.clientY;
  } else if (e.type === "touchstart") {
    const touch = e.touches[0];
    clientX = touch.clientX;
    clientY = touch.clientY;
  }

  pointer.x = clientX / window.innerWidth;
  pointer.y = clientY / window.innerHeight;
  pointer.clicked = true;
  isRendering = true;
}

window.addEventListener("click", handleClickOrTouch);
window.addEventListener("touchstart", handleClickOrTouch);

render();

function initScene() {
  renderer = new THREE.WebGLRenderer({
    canvas: canvasEl,
    alpha: true,
  });
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

  shaderScene = new THREE.Scene();
  mainScene = new THREE.Scene();
  sceneTest = new THREE.Scene();

  camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
  clock = new THREE.Clock();

  renderTargets = [
    new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight),
    new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight),
  ];

  const planeGeometry = new THREE.PlaneGeometry(2, 2);

  shaderMaterial = new THREE.ShaderMaterial({
    uniforms: {
      u_ratio: { type: "f", value: window.innerWidth / window.innerHeight },
      u_point: { type: "v2", value: new THREE.Vector2(pointer.x, pointer.y) },
      u_time: { type: "f", value: 0 },
      u_stop_time: { type: "f", value: 0 },
      u_stop_randomizer: { type: "v3", value: new THREE.Vector2(0, 0, 0) },
      u_texture: { type: "t", value: null },
      u_background_color: { type: "v3", value: backgroundColor },
    },
    vertexShader: vertexShader,
    fragmentShader: fragmentShader,
    transparent: true,
  });

  basicMaterial = new THREE.MeshBasicMaterial({
    transparent: true,
  });
  const backgroundColorMaterial = new THREE.MeshBasicMaterial({
    color: backgroundColor,
    transparent: true,
  });

  const planeBasic = new THREE.Mesh(planeGeometry, basicMaterial);
  const planeShader = new THREE.Mesh(planeGeometry, shaderMaterial);
  const coloredPlane = new THREE.Mesh(planeGeometry, backgroundColorMaterial);

  shaderScene.add(planeShader);
  mainScene.add(coloredPlane);

  renderer.setRenderTarget(renderTargets[0]);
  renderer.render(mainScene, camera);

  mainScene.remove(coloredPlane);
  mainScene.add(planeBasic);
}

function render() {
  requestAnimationFrame(render);
  const delta = clock.getDelta();

  if (isRendering) {
    shaderMaterial.uniforms.u_texture.value = renderTargets[0].texture;
    shaderMaterial.uniforms.u_time.value = clock.getElapsedTime() + 0.9; // offset for 1st flower color

    if (pointer.clicked) {
      shaderMaterial.uniforms.u_point.value = new THREE.Vector2(
        pointer.x,
        1 - pointer.y
      );
      shaderMaterial.uniforms.u_stop_randomizer.value = new THREE.Vector3(
        Math.random(),
        Math.random(),
        Math.random()
      );
      if (isStart) {
        shaderMaterial.uniforms.u_stop_randomizer.value = new THREE.Vector3(
          0.5,
          1,
          1
        );
        isStart = false;
      }
      shaderMaterial.uniforms.u_stop_time.value = 0;
      pointer.clicked = false;
    }
    shaderMaterial.uniforms.u_stop_time.value += delta;

    renderer.setRenderTarget(renderTargets[1]);
    renderer.render(shaderScene, camera);

    basicMaterial.map = renderTargets[1].texture;

    renderer.setRenderTarget(null);
    renderer.render(mainScene, camera);

    let tmp = renderTargets[0];
    renderTargets[0] = renderTargets[1];
    renderTargets[1] = tmp;
  }
}

function updateSize() {
  shaderMaterial.uniforms.u_ratio.value =
    window.innerWidth / window.innerHeight;
  renderer.setSize(window.innerWidth, window.innerHeight);
}
slackermorris commented 1 year ago

Could this at all be useful in better boilerplating my project?

slackermorris commented 1 year ago

This is helpful in refactoring what I have:

slackermorris commented 1 year ago

O.K. I pretty much have the branch where I want it: the flower animation has been integrated and works.

The styling is borked.

I think before I proceed that I should introduce React to the project. This way I can write the flower animation as a React Component.

slackermorris commented 1 year ago

Yeah, so I stripped out a lot of the initial boilerplate for the flower animation stuff.

slackermorris commented 1 year ago

I'm wondering whether the webgl stuff should be in the scripts directory or not.