# Making rain drop collision

**URL:** <https://discourse.threejs.org/t/making-rain-drop-collision/66226>\
**Category:** Questions\
**Created:** [May 31, 2024, 4:19am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226 "2024-05-31T04:19:30Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![PhiNM6296](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/phinm6296/32/47363_2.png) [@PhiNM6296](https://discourse.threejs.org/u/PhiNM6296)\
**Post date:** [May 31, 2024, 4:19am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/1 "2024-05-31T04:19:30Z")

</div>

I’m trying to make a scene, with rain drops and a 3D model of a roof. For now, i’m trying to detect the collision of the rain drops to the roof, then make a splash effect when there’s a collision. I read that you can use a bound box, but my bound box for the 3D model looks like this

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/0/d/0dccce710ffbb496e201247bd8051a4d81d5a404.jpeg)

Here is my code for loading the 3D model and creating bound box:

```javascript
const loader = new GLTFLoader();

loader.load('./simple_roof_model/scene.gltf', function (gltf) {
  scene.add(gltf.scene);
  gltf.scene.scale.set(0.01, 0.01, 0.01);
  gltf.scene.position.set(0, -3, 0);
  gltf.scene.rotation.set.y = 1.5;
  const model = gltf.scene;
  // Update the model's matrix to apply transformations
  model.updateMatrixWorld();

  // Get the bounding box of the model
  const modelBoundingBox = new THREE.Box3().setFromObject(model);

  // Create a wireframe geometry based on the bounding box
  const wireframeGeometry = new THREE.BoxGeometry().setFromPoints([
      modelBoundingBox.min,
      modelBoundingBox.max
  ]);

  // Create a wireframe material
  const wireframeMaterial = new THREE.MeshBasicMaterial({
      color: 0x00ff00, // Green color
      wireframe: true // Render as wireframe
  });

  // Create the wireframe mesh
  const wireframeMesh = new THREE.Mesh(wireframeGeometry, wireframeMaterial);

  // Add the wireframe mesh to the scene
  scene.add(wireframeMesh);
});

```

How do i fix the bound box to accurately cover the model. And do you have any suggestion on how to make the splash effect?

---

<div class="post-metadata">

**Author:** ![mjurczyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mjurczyk/32/10995_2.png) [@mjurczyk](https://discourse.threejs.org/u/mjurczyk)\
**Post date:** [May 31, 2024, 4:28am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/2 "2024-05-31T04:28:16Z")

</div>

Technically, if you don’t spawn too many drops per second, it shouldn’t be crazy expensive to just do a raycast from rain drop spawn point towards its falling direction - and just measure the distance to the collision (then despawn the raindrop as soon as it crosses that distance.)

But if you’re creating 1000s of these raindrops and want something quicker:

1. Create an InstancedMesh of the rain drop particles
2. Create a spawn surface (plane that limits the area at which the rain drops can spawn and start falling down from.)
3. Place a camera at the center of that plane, point it downwards and render DepthTexture from that camera perspective to a RenderTarget texture. That way you’ve just did all the raycasting in a single RT.
4. Whenever you spawn a new raindrop, just sample the RT at the position at which you create the drop (or at the position it will fall at, if it’s falling at an angle.), and calculate the maximum distance drop can travel before splashing.

Ain’t no need to base your rain / particle systems on manually set bounding boxes.

---

<div class="post-metadata">

**Author:** ![PhiNM6296](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/phinm6296/32/47363_2.png) [@PhiNM6296](https://discourse.threejs.org/u/PhiNM6296)\
**Post date:** [May 31, 2024, 6:51am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/4 "2024-05-31T06:51:16Z")

</div>

Does make the plane to limit the area where the rain can spawn and fall down make a square where there’s no rain at all? I want to make a 3D scene where a can move the camera around.  
Or do you mean like this, i’m trying to make a plane that when the drop get in contact with the plane, the drop will reset/ make spalsh effect (but i’m struggling to write the logic for that)

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/6/a/6aaf49e4ff1b47697a080227d3900f3031db738d.jpeg)

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [May 31, 2024, 1:40pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/5 "2024-05-31T13:40:21Z")

</div>

> [@mjurczyk](#):
>
> a RenderTarget texture

Had the same thought.  
Seems, it’s working 🤝 (50k raindrops)

 ![изображение](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/c/a/cafd3ce475568b7c3e23bee6f3ffafe888be41d7.jpeg)

---

<div class="post-metadata">

**Author:** ![PhiNM6296](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/phinm6296/32/47363_2.png) [@PhiNM6296](https://discourse.threejs.org/u/PhiNM6296)\
**Post date:** [May 31, 2024, 3:31pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/7 "2024-05-31T15:31:40Z")

</div>

Can you guys share the code or related document or just anything in general to be able to implement this? I have no idea at all how to do it.

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [May 31, 2024, 3:49pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/8 "2024-05-31T15:49:10Z")

</div>

How to setup a WebGLRenderTarget with DepthTexture: [three.js examples](https://threejs.org/examples/#webgl_depth_texture)

How to render to the render target with `OrthographicCamera`, this is what I could recall quickly: [Running in the field of instances](https://discourse.threejs.org/t/running-in-the-field-of-instances/52934)

Also, used [layers](https://threejs.org/docs/index.html#api/en/core/Layers) for cameras and objects. For example, when you render with the orthographic camera to the render target, you don’t need it to “see” the rain, so the camera “sees” objects at the layer 1.

---

<div class="post-metadata">

**Author:** ![PavelBoytchev](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pavelboytchev/32/38639_2.png) [@PavelBoytchev](https://discourse.threejs.org/u/PavelBoytchev)\
**Post date:** [May 31, 2024, 4:20pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/9 "2024-05-31T16:20:04Z")

</div>

Three.js is like an illusionist’s hat. You can pull out real magic. If your browser supports WebGPU, here is something to tease you:

[https://threejs.org/examples/#webgpu\_compute\_particles\_rain](https://threejs.org/examples/#webgpu_compute_particles_rain)

---

<div class="post-metadata">

**Author:** ![PhiNM6296](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/phinm6296/32/47363_2.png) [@PhiNM6296](https://discourse.threejs.org/u/PhiNM6296)\
**Post date:** [June 1, 2024, 6:34pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/10 "2024-06-01T18:34:23Z")

</div>

I’m trying to follow your first way, implementing this function to update the rain and detect collision. My logic is that if the y coordinate of the rain drop is close to the y coordinate of the collision point, it\s should be the collision, then it will print out “met”. However, even though the particle met the plane in the scene, no message was printed out. Could you take a look and see what is the problem?

````javascript
function updateRainPositions() {
    intersectionPoints.length = 0; // Clear intersection points array

    raindrops.forEach((raindrop, index) => {
        // Update position
        raindrop.y -= raindrop.velocity*0.1; // Move the raindrop upward

        // Check if raindrop is out of screen
        if (raindrop.y < -3.5) {
            raindrop.y = 10; // Reset position above the screen
            raindrop.velocity = THREE.MathUtils.randFloat(0.1, 0.5); // Reset velocity
            console.log("reset");
        }

        // Raycast to check for collision with the plane
        const raycaster = new THREE.Raycaster(new THREE.Vector3(raindrop.x, raindrop.y, raindrop.z), new THREE.Vector3(0, -1, 0));
        const intersects = raycaster.intersectObject(planeMesh);

        // Raycast to check for collision with the second plane
        const intersects2 = raycaster.intersectObject(roofMesh);

        let collided = false; // Flag to track collision
        let intersectionPoint = null; // Store intersection point

        // Check for intersection with the plane
        if (intersects.length > 0) {
            intersectionPoint = intersects[0].point; // Get the intersection point
            collided = intersectionPoint.y >= raindrop.y; // Check if collision happened at or below the raindrop
            // console.log(intersectionPoint.y);
        
          }

        // Check for intersection with the second plane
        if (!collided && intersects2.length > 0) {
            intersectionPoint = intersects2[0].point;
            collided = intersectionPoint.y >= raindrop.y;
            // console.log("Intersection point:")
            // console.log(intersectionPoint.y);
            // console.log("rain drop:")
            // console.log(raindrop.y);

        
          }

        // Reset raindrop if collision detected
        if (collided) {
            // Store the intersection point for visualization
            intersectionPoints.push(intersectionPoint);
            // console.log(raindrop.x);
            // console.log(raindrop.y);
            // console.log(raindrop.z);
            const tolerance = 0.1 * raindrop.velocity;
            if (intersectionPoint.y - raindrop.y <= tolerance) {
                console.log("met");
                // Reset raindrop position and velocity
            }
            // raindrop.y -= raindrop.velocity; // Move the raindrop upward
            // // Reset raindrop position and velocity
            // raindrop.y = 10; // Reset position above the screen
            // raindrop.velocity = THREE.MathUtils.randFloat(0.1, 0.5); // Reset velocity
        }
    });

    // Update rainMesh positions
    for (let i = 0; i < gCount; i++) {
        const raindrop = raindrops[i];
        const matrix = new THREE.Matrix4().makeTranslation(raindrop.x, raindrop.y, raindrop.z);
        rainMesh.setMatrixAt(i, matrix);
    }

    rainMesh.instanceMatrix.needsUpdate = true; // Update instance matrix

    // Visualize intersection points
    visualizeIntersectionPoints();
}```
````

---

<div class="post-metadata">

**Author:** ![mjurczyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mjurczyk/32/10995_2.png) [@mjurczyk](https://discourse.threejs.org/u/mjurczyk)\
**Post date:** [June 2, 2024, 6:05am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/11 "2024-06-02T06:05:39Z")

</div>

You shouldn’t do the raycasting on every frame - it’s expensive and the result will always be the same (for collisions with static world.)

Only when you spawn a raindrop do the raycast, one time per drop for the entire lifetime of the raindrop - read the length of the vector `rainDropStart.sub(intersections[0].point)`. Then on every frame move the raindrop along it’s path and calculate current distance of the raindrop from it’s starting position. Is the distance between raindrop and the starting position longer than between starting position and the raycaster intersection? Then splash the raindrop.

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [June 4, 2024, 12:22pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/12 "2024-06-04T12:22:37Z")

</div>

Demo, if somebody’s interested 🙂 :  
https://codepen.io/prisoner849/embed/preview/yLWMLjK?default-tabs=js%2Cresult&height=300&host=https%3A%2F%2Fcodepen.io&slug-hash=yLWMLjK

---

<div class="post-metadata">

**Author:** ![Lawrence3DPK](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/lawrence3dpk/32/29184_2.png) [@Lawrence3DPK](https://discourse.threejs.org/u/Lawrence3DPK)\
**Post date:** [June 4, 2024, 6:55pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/13 "2024-06-04T18:55:56Z")

</div>

Genius! This makes me think, water, earth, wind, fire are all in the same category for a reason… Surfaced based fire could essentially be the inverted time scale here with some noise growth 🤔 following suit with both wind and earth / ‘dust’

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [June 4, 2024, 7:19pm UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/14 "2024-06-04T19:19:17Z")

</div>

> [@Lawrence3DPK](#):
>
> dust

I tried to emulate it once 🙂: [Noisy Mountains](https://discourse.threejs.org/t/noisy-mountains/35805)  
It wasn’t the approach with `DepthTexture` though.

---

<div class="post-metadata">

**Author:** ![wenrenqiang](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/wenrenqiang/32/54020_2.png) [@wenrenqiang](https://discourse.threejs.org/u/wenrenqiang)\
**Post date:** [March 7, 2025, 9:57am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/15 "2025-03-07T09:57:00Z")

</div>

[three.js示例](https://threejs.org/examples/?q=rain#webgpu_compute_particles_rain)  
This case is similar to the case of Three.js, but it cannot be scaled or rotated using a transformation controller to directly control the direction and range of rainwater. You once had a version that used line materials to make rain, but I don’t know if you still have an impact. This line material version of rain can be scaled or rotated directly using a transformation controller to control the range and direction of rainwater. Do you have a TSL version

 ![企业微信截图_17413412709855](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/d/3/d3bca697bb6e3851f10f1a9785398b6f6705d46a.png)

---

<div class="post-metadata">

**Author:** ![wenrenqiang](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/wenrenqiang/32/54020_2.png) [@wenrenqiang](https://discourse.threejs.org/u/wenrenqiang)\
**Post date:** [March 10, 2025, 11:13am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/16 "2025-03-10T11:13:33Z")

</div>

This rain cannot be dragged with a transformation controller

---

<div class="post-metadata">

**Author:** ![wenrenqiang](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/wenrenqiang/32/54020_2.png) [@wenrenqiang](https://discourse.threejs.org/u/wenrenqiang)\
**Post date:** [March 10, 2025, 11:13am UTC](https://discourse.threejs.org/t/making-rain-drop-collision/66226/17 "2025-03-10T11:13:54Z")

</div>

tsl verison
