在 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;
}
// ...
}
我正在尝试从 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;
}
// ...
}