Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object Overflow Clipping Three JS

Tags:

three.js

webgl

Using three js is there anyway to define a clipping region for an object? I have for example a parent which contains child objects, I would like to clip the child objects based on the viewport.

Something like...

// Create container and children
var container = new THREE.Object3D();
for(var i = 0; i < 100; i++) {
    var geometry = new THREE.PlaneGeometry(i, 0, 0);
    var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
    var child = new THREE.Mesh(geometry, material);
    container.add(child);
}

// Create bounding box which is my viewport
var geom = new THREE.Geometry();
geom.vertices.push(new THREE.Vector3(0, 0, 0));
geom.vertices.push(new THREE.Vector3(10, 0, 0));
geom.vertices.push(new THREE.Vector3(10, 1, 0));
geom.vertices.push(new THREE.Vector3(0, 1, 0));
geom.computeBoundingBox();

// Magic property (THIS DOESNT EXIST)
container.clipRegion = geom.boundingBox;

The final part doesn't exist but is there any way to achieve this with three js? I potentially want to animate the children within the parent and only show the visible region defined by the bounding box.

Update, Added the following image to describe my problem.

clip region

The resulting red area is the region I want to make visible, whilst masking anything that lies outside of this region. All other content should be visible.

like image 578
fungus1487 Avatar asked Nov 13 '22 12:11

fungus1487


1 Answers

I have been able to clip an object with another.

See the result here

fiddle

In this fiddle you will see a cube being clip by an sphere. Since this is a demo, there are some things that are not the final code.

You have in the right hand of the screen another camera view, where you see the scene from a high, static point view.

Also, the part of the cube that should be clipped, instead of this is showed green. In the fragment shader, you have to uncomment the discard statement to achieve real clipping.

if (shadowColor.r < 0.9) {
    gl_FragColor = vec4 (0.3, 0.9, 0.0, 1.0);
} else {
    gl_FragColor = vec4 (0.8, 0.8, 0.8, 1.0);
    // discard;
}

It works by creating a spot light that can cast shadows

clippingLight = new THREE.SpotLight (  0xafafaf, 0.97  );
clippingLight.position.set (100, 200, 1400);
clippingLight.castShadow = true;
scene.add (clippingLight);

The object that has to do the clipping casts shadows, and the object to be clipped receives shadows.

Then, in the animate , we set this light to the camera location

function animate() {
cameraControls.update();
clippingLight.position.x = camera.position.x;
clippingLight.position.y = camera.position.y;
clippingLight.position.z = camera.position.z;
requestAnimationFrame(animate);
}

Now, the parts that have to be visible in the clipped object are the ones at the shadow. We need a shader that handles that. The frag shader code is take from the standard one in the three.js library, just slightly modified.

I am very new working with three.js, so probably there are a lot of thing in the code that can be done better. Just take the idea :-)

like image 90
vals Avatar answered Nov 15 '22 05:11

vals