I am trying to clip a volume from all three planes in ThreeJS to look into the inner structure.
Clipping is done inspired and implemented in fragment shader by discarding the drawing of the pixel if it is beyond your clipping limit:
gl_FragColor = accumulatedColor;
if(worldSpaceCoords.x < xClippingPlaneMin) discard;
if(worldSpaceCoords.x < xClippingPlaneMin) discard;
if(worldSpaceCoords.z < zClippingPlaneMin) discard;
if(worldSpaceCoords.z > zClippingPlaneMax) discard;
if(worldSpaceCoords.y < yClippingPlaneMin) discard;
if(worldSpaceCoords.y > yClippingPlaneMax) discard;
And have circulated the above information by passing through the shader material (Two pass Volume Rendering) as shown in below code.
var materialFirstPass = new THREE.ShaderMaterial( {
vertexShader: document.getElementById( 'vertexShaderFirstPass' ).textContent,
fragmentShader: document.getElementById( 'fragmentShaderFirstPass' ).textContent,
side: THREE.BackSide,
} );
materialSecondPass = new THREE.ShaderMaterial( {
vertexShader: document.getElementById( 'vertexShaderSecondPass' ).textContent,
fragmentShader: document.getElementById( 'fragmentShaderSecondPass' ).textContent,
side: THREE.FrontSide,
depthWrite: false,
uniforms: { tex: { type: "t", value: rtTexture },
cubeTex: { type: "t", value: cubeTextures['bonsai'] },
transferTex: { type: "t", value: transferTexture },
steps : {type: "1f" , value: guiControls.steps },
alphaCorrection : {type: "1f" , value: guiControls.alphaCorrection },
xClippingPlaneMin : {type: "1f" , value: guiControls.xClippingPlaneMin },
xClippingPlaneMax : {type: "1f" , value: guiControls.xClippingPlaneMax },
yClippingPlaneMin : {type: "1f" , value: guiControls.yClippingPlaneMin },
yClippingPlaneMax : {type: "1f" , value: guiControls.yClippingPlaneMax },
zClippingPlaneMin : {type: "1f" , value: guiControls.zClippingPlaneMin },
zClippingPlaneMax : {type: "1f" , value: guiControls.zClippingPlaneMax }
},
});
sceneFirstPass = new THREE.Scene();
sceneSecondPass = new THREE.Scene();
var boxGeometry = new THREE.BoxGeometry(1.0, 1.0, 1.0);
boxGeometry.doubleSided = true;
var meshFirstPass = new THREE.Mesh( boxGeometry, materialFirstPass );
var meshSecondPass = new THREE.Mesh( boxGeometry, materialSecondPass );
sceneFirstPass.add( meshFirstPass );
sceneSecondPass.add( meshSecondPass );
It looks something of this sort black boundary which I want to be the rendered surface.
Update : My motive is to look inside the Volume clipping from all 3 direction plane X, Y and Z respectively. You can think of slicing too like I want to look into the volume at some slice.
I looked into these examples Clipping, Advance Clipping and Intersection Clipping , but these were not of much use so used the coordinate based discarding and clipping way to achieve my goal.
As discussed on Three.js Discourse, the problem with your approach is that by discarding the pixel, on fragment shader, you prevent it from being rendered at all.
The correct approach would be to prevent the ray-marching from accumulating color and alpha if the ray position is outside your clipping box. Clipping box coordinates must be within [0,1] space.
bool withinBoundaries( vec3 pos ) {
if (
pos.x < xClippingPlaneMin ||
pos.y < yClippingPlaneMin ||
pos.z < zClippingPlaneMin ||
pos.x > xClippingPlaneMax ||
pos.y > yClippingPlaneMax ||
pos.z > zClippingPlaneMax
) return false;
return true;
}
// ...
//Perform the ray marching iterations
for( int i = 0; i < MAX_STEPS; i++) {
// ...
if ( withinBoundaries( currentPosition ) ) {
//Perform the composition.
accumulatedColor += colorSample * alphaSample;
//Store the alpha accumulated so far.
accumulatedAlpha += alphaSample;
}
// ...
}