1

It is an experiment.. this geometry has this strange behavior where if i update only one attribute it looks correct: the shape 'bubbles' or the surface changes color with noise .. but when both color and position are updated it doesn't appear as it should: one of them seems to fail...

import { useFrame } from '@react-three/fiber'
import React, { useRef, useEffect } from 'react'
import { createNoise3D, createNoise4D } from 'simplex-noise'
import alea from 'alea';
import * as THREE from 'three'

function Background(props) {
  const refPlane = useRef()
  const refSphere = useRef()
  const prng = alea('seed')
  const noise3D = createNoise3D(prng)
  const noise4D = createNoise4D(prng)
  let posPlane, posSphere;
  let newColorPlane = new Float32Array(12)
  let newColorSphere = new Float32Array(12675)
  let newPosSphere = new Float32Array(12675)
  let attrColorSphere = new THREE.BufferAttribute(newColorSphere, 3)
  let attrColorPlane = new THREE.BufferAttribute(newColorPlane, 3)
  let attrPosSphere = new THREE.BufferAttribute(newColorSphere, 3)

  function mapRange(value, a, b, c, d) {
    value = (value - a) / (b - a);
    return c + value * (d - c);
  }

  useEffect(() => {
    posPlane = refPlane.current.geometry.getAttribute('position')
    posSphere = refSphere.current.geometry.getAttribute('position')
  }, []);

  function updatePosPlane(positionPlane, time) {
    for (let i = 0; i < (positionPlane.count * 3); i += 3) {
      const x = positionPlane.array[i];
      const y = positionPlane.array[i + 1];
      const noise = (noise3D(x, y, time / 2));
      const hue = mapRange(noise, -1, 1, 0, 1);
      const color = new THREE.Color();
      color.setHSL(hue, 0.9, 0.25);
      newColorPlane[i] = color.r;
      newColorPlane[i + 1] = color.g;
      newColorPlane[i + 2] = color.b;
    }
    return newColorPlane
  }
  function updateColorSphere(positionSphere, time) {
    for (let i = 0; i < (positionSphere.count * 3); i += 3) {
      const x = positionSphere.array[i];
      const y = positionSphere.array[i + 1];
      const z = positionSphere.array[i + 2];
      const noise = (noise4D(x / 5, y / 5, z / 5, time / 10));
      const hue = mapRange(noise, -1, 1, 0, 1);
      const color = new THREE.Color();
      color.setHSL(hue, 0.9, 0.25);
      newColorSphere[i] = color.r;
      newColorSphere[i + 1] = color.g;
      newColorSphere[i + 2] = color.b;
    }
    return newColorSphere
  }

  function updatePosSphere(positionCurve, time) {
    for (let i = 0; i < (positionCurve.count * 3); i += 3) {
      const x = positionCurve.array[i];
      const y = positionCurve.array[i + 1];
      const z = positionCurve.array[i + 2];
      const noise = (noise4D(x / 5, y / 5, z / 5, time));
      const vec = new THREE.Vector3(x, y, z);
      const newVec = vec.addScaledVector(vec, noise / 2);
      newPosSphere[i] = newVec.getComponent(0);
      newPosSphere[i + 1] = newVec.getComponent(1);
      newPosSphere[i + 2] = newVec.getComponent(2);
    }
    return newPosSphere;
  }

  useFrame(({ clock }) => {
    const a = clock.getElapsedTime()
    refPlane.current.geometry.setAttribute('color', attrColorPlane.set(updatePosPlane(posPlane, a)))
    refPlane.current.geometry.attributes.color.needsUpdate = true
    refSphere.current.geometry.setAttribute('position', attrPosSphere.set(updatePosSphere(posSphere, a)))
    refSphere.current.geometry.setAttribute('color', attrColorSphere.set(updateColorSphere(posSphere, a)))
    refSphere.current.geometry.attributes.position.needsUpdate = true
    refSphere.current.geometry.attributes.color.needsUpdate = true
    refSphere.current.rotation.y = a
  })
  return (
    <>
      <mesh
        {...props}
        ref={refPlane}
        position={[0, 0, 0]}
        scale={[20, 20, 0]}>
        <planeGeometry />
        <meshBasicMaterial color='white' vertexColors needsUpdate />
      </mesh>
      <mesh
        {...props}
        ref={refSphere}
        position={[0, 0, 0]}>
        <sphereGeometry args={[2, 64, 64]} />
        <meshBasicMaterial vertexColors needsUpdate />

      </mesh>
    </>

  )
}

export default Background

I have tried various things and searched here for various possible solutions but I'm new to React and Three.js and I'm probably doing something wrong. Any suggestion is welcome!

  • You should probably initiate your `attrPosSphere` to `let attrPosSphere = new THREE.BufferAttribute(newPosSphere, 3)` instead of newColorSphere. – Nils Kähler Jun 16 '23 at 09:54
  • @NilsKähler found the error! Thank you so much I would have kept breaking my head for a long time.. :-) – Luca Ponzanelli Jun 16 '23 at 10:45

0 Answers0