在 Three.Js 中剪切一个体积,给出黑色区域而不是内部 Material

Clipping a volume in Three.Js giving Black area instead of Inner Material

我正在尝试从 ThreeJS 中的所有三个平面剪辑一个体积以查看内部结构。

剪辑是在片段着色器中启发和实现的,方法是丢弃超出剪辑限制的像素绘图:

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;

并通过着色器material(两次通过体积渲染)传递上述信息,如下面的代码所示。

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 );

它看起来像这种黑色边界,我想将其作为渲染表面。

更新 :我的动机是分别从所有 3 个方向平面 X、Y 和 Z 查看体积剪裁内部。你也可以考虑切片,就像我想在某个切片上查看体积。

我研究了这些例子Clipping, Advance Clipping and Intersection Clipping ,但这些例子没什么用,所以使用基于坐标的丢弃和裁剪方式来实现我的目标。

正如在 Three.js Discourse 上讨论的那样,您的方法存在的问题是,通过在片段着色器上丢弃像素,您根本无法渲染它。

如果光线位置在您的裁剪框之外,正确的方法是防止 ray-marching 累积颜色和 alpha。裁剪框坐标必须在 [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;
    }
    // ...
}