How to Create a Realistic Bubble Material in Three.js?

Hi everyone,

I’m working on a project where I need to create a realistic bubble material for a sphere. I’ve already achieved the desired look in Blender, but when I export it as a GLTF file and import it into Three.js, the effect doesn’t appear.

What I’m Trying to Achieve:

I want the sphere to have:

  • Gradient reflections like a real soap bubble (iridescent, colorful effect).
  • Light interaction that changes as the bubble rotates.
  • Transparency with realistic reflections.

Here’s a reference image of what I’m trying to create:

Current Approach:

I’m using React-Three-Fiber (R3F) to implement this, and this is my current code:

<mesh
  geometry={new THREE.SphereGeometry(5.1, 64, 64)}
  material={
    new THREE.MeshPhysicalMaterial({
      map: textureLoader.load(texture),
      transmission: 1, // Full transparency
      roughness: 0,
      metalness: 0,
      ior: 1.35, // Index of refraction
      depthTest: false,
    })
  }
/>
<R3F.Environment preset="sunset" />

While this renders a transparent sphere with reflections, the gradient reflection effect (like in a soap bubble) is missing.

My Problem:

  1. The bubble doesn’t have the iridescent gradient reflections that change with light and angle.
  2. Blender’s material doesn’t translate properly to Three.js.
    ( I used Mix Shader and Glossy Shader)

Questions:

  1. How can I achieve a realistic bubble material in Three.js that mimics thin-film interference? Should I use a custom shader, or can I tweak the existing MeshPhysicalMaterial?
  2. Are there any libraries, techniques, or examples you can recommend for recreating the bubble effect?
  3. Is there a way to directly replicate Blender’s shader effect in Three.js?

I’d appreciate any code examples, resources, or guidance to help me achieve this effect. Thank you so much for your help! :pray:

not the solution, but you are re-creating these objects on every component render. see Objects, properties and constructor arguments - React Three Fiber i would also avoid using any and all threejs loading stuff like textureLoader.load(texture). when things load randomly and finish whenever, then nothing can deterministically use that component without knowing it or having a specific contract with it.

const texture = useTexture(textureUrl)
...
<mesh scale={5.1}>
  <sphereGeometry args={[1, 64, 64]} />
  <meshPhysicalMaterial map={texture} transmission={1} roughness={0}
    metalness={0} ior={1.35} depthTest={false} />
<mesh/>

threejs btw has thin film reflections called iridescence on the meshphysicalmaterial. the streaks in your reference could be done with an iridescence-map.

1 Like

something like this maybe https://codesandbox.io/p/sandbox/focused-kirch-9dyrgh?file=%2Fsrc%2FApp.js

2 Likes

Have you seen before/after montages of matte-painters? Their bubbles use 30+ matte layers to simulate subsurface scattering. One bubble-to-bubble projection took 30+ hours to paint. Your shader could use a spectral MIP under the covers.

Any progress,
Prinsck8s Pea

1 Like

Wow, this is exactly what I was looking for! Apologies for the delayed response, but I just wanted to say a big thank you for your help.

Your explanation and the CodeSandbox example are incredibly helpful. The tip about using iridescence on MeshPhysicalMaterial is perfect for the effect I wanted to achieve. I’ll be diving into this right away!

Thank you so much again for taking the time to provide such detailed advice. I really appreciate it! :blush:

Thank you so much for your detailed response! I really appreciate your suggestions. If I understand correctly, you’re recommending I explore using a spectral MIP approach to improve the shader, particularly for effects like subsurface scattering or iridescence, right?

Up until now, I’ve been using MeshTransmissionMaterial from R3F drei, but I’ll definitely try your advice to see how it compares.

Also, I wanted to mention that I had some difficulty fully understanding your explanation because translation tools didn’t interpret everything accurately. If you could simplify or clarify any part, that would be super helpful! Either way, I’ll experiment further based on your advice. Thanks again for pointing me in the right direction!

Yes, a spectral mip.

1 Like