Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Drei Vanilla"’s MeshTransmissionMaterial renders only black sphere #874

Closed
AndreasFaust opened this issue Nov 29, 2024 · 4 comments
Closed

Comments

@AndreasFaust
Copy link

AndreasFaust commented Nov 29, 2024

Describe the bug

This is more likely me doing something wrong than a bug. I am trying to setup a simple scene, where a sphere is put in front of a plane with a photo.
The sphere has Meshtransmissionmaterial applied to it. It seems to work but the sphere is only black instead of transparent.

Bildschirmfoto 2024-11-29 um 01 05 56
<script setup lang="ts">
import {
  Mesh,
  MeshStandardMaterial,
  PlaneGeometry,
  SphereGeometry,
} from "three";

import { MeshTransmissionMaterial } from "@pmndrs/vanilla";
import { TresCanvas, useTexture } from "@tresjs/core";

const geometry = new SphereGeometry(0.4);
const material = new MeshTransmissionMaterial({
  _transmission: 1,
  thickness: 0,
  roughness: 0,
  chromaticAberration: 0.03,
  distortion: 0,
  distortionScale: 0.5,
  temporalDistortion: 0.0,
});
const meshWithMaterial = new Mesh(geometry, material);
const { map } = await useTexture({
  map: "/lola.jpg",
});
const meshPlane = new Mesh(
  new PlaneGeometry(0.7, 0.7),
  new MeshStandardMaterial({ map })
);
</script>

<template>
  <TresCanvas>
    <TresPerspectiveCamera :position="[0, 0, 4]" />
    <TresGroup :scale="3">
      <primitive :object="meshWithMaterial" />
      <primitive :object="meshPlane" />
    </TresGroup>
    <TresHemisphereLight :intensity="3" />
  </TresCanvas>
</template>
@AndreasFaust
Copy link
Author

AndreasFaust commented Nov 30, 2024

I found an older version of MeshTransmissionMaterial that works and set up an example:
https://stackblitz.com/edit/nuxt-starter-19cxrs

Bildschirmfoto 2024-11-30 um 15 00 29

It reproduces an example of React Three Fiber.
I also reproduced the noise-function and put it into a composible. It maybe could be something for Cientos, @alvarosabu ?

// useNoise.ts
import { useLoop } from '@tresjs/core';
import { shallowRef } from '@vue/reactivity';
import { ref } from 'vue';

export default function useNoise({ intensity = 0.03, speed = 0.2 } = {}) {
  const mesh = shallowRef();

  const originalPositions = ref();
  const time = ref(0);

  const { onBeforeRender } = useLoop();

  onBeforeRender(({ delta }) => {
    time.value += delta * speed;

    if (mesh.value && mesh.value.geometry) {
      const positions = mesh.value.geometry.attributes.position.array;

      // Store original positions if not already stored
      if (!originalPositions.value) {
        originalPositions.value = new Float32Array(positions.length);
        for (let i = 0; i < positions.length; i++) {
          originalPositions.value[i] = positions[i];
        }
      }
      // Update each vertex position with noise
      for (let i = 0; i < positions.length; i += 3) {
        const x = originalPositions.value[i];
        const y = originalPositions.value[i + 1];
        const z = originalPositions.value[i + 2];

        // Create noise based on position and time
        const noise =
          (Math.sin(x * 5 + time.value) +
            Math.sin(y * 5 + time.value) +
            Math.sin(z * 5 + time.value)) *
          intensity;

        // Apply noise in the direction of the vertex normal
        const length = Math.sqrt(x * x + y * y + z * z);
        positions[i] = x + (x / length) * noise;
        positions[i + 1] = y + (y / length) * noise;
        positions[i + 2] = z + (z / length) * noise;
      }

      mesh.value.geometry.attributes.position.needsUpdate = true;
      mesh.value.rotation.y += delta * 0.2;
      mesh.value.rotation.z += delta * 0.1;
    }
  });

  return { mesh };
}

@AndreasFaust
Copy link
Author

By the way:

  1. I could not make the FontLoader work in pure Vue/Vite. I could not find the right path to the font, so I had to switch to Nuxt. If somebody knows where to put the font and how the path has to be named, it would be great for the docs.
  2. There is a bug with useLoop: If I call it on the outside of the TresCanvas it breaks. So I can just call it in child-components. Is there a way to fix this?

@andretchen0
Copy link
Contributor

Hey @AndreasFaust, this is quite useful.

It reproduces an example of React Three Fiber. I also reproduced the noise-function and put it into a composible. It maybe could be something for Cientos, @alvarosabu ?

For MeshRefractionMaterial, definitely. Alvaro and I were just discussing that on the Discord. (Fwiw, we were discussing whether or not to add the bvh dependency that the Drei component uses. We decided to add it.)

For useNoise, is there a use case beyond MeshRefractionMaterial?

There is a bug with useLoop: If I call it on the outside of the TresCanvas it breaks. So I can just call it in child-components. Is there a way to fix this?

It can't be worked around with useLoop unfortunately. Behind the scenes, useLoop uses Vue's provide/inject. The provide is done by the TresCanvas. So the inject is only available in subcomponents.

@andretchen0
Copy link
Contributor

  1. I could not make the FontLoader work in pure Vue/Vite. I could not find the right path to the font, so I had to switch to Nuxt. If somebody knows where to put the font and how the path has to be named, it would be great for the docs.

Thanks for the feedback. I have useFont on my TODO list for Cientos. I'll test out local fonts there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants