在 Three.Js 中剪裁一个体积,给出黑色区域而不是内部材质
Posted
技术标签:
【中文标题】在 Three.Js 中剪裁一个体积,给出黑色区域而不是内部材质【英文标题】:Clipping a volume in Three.Js giving Black area instead of Inner Material 【发布时间】:2019-09-27 15:14:30 【问题描述】:我正在尝试从 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;
并通过shader材质(Two pass Volume Rendering)传递了上述信息,如下代码所示。
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 和 Intersection Clipping ,但这些示例并没有多大用处,因此使用基于坐标的丢弃和裁剪方式来实现我的目标。
【问题讨论】:
【参考方案1】:正如Three.js Discourse 所讨论的那样,您的方法的问题在于,通过在片段着色器上丢弃像素,您根本无法对其进行渲染。
如果光线位置在您的剪切框之外,正确的方法是防止光线行进累积颜色和 alpha。剪切框坐标必须在 [0,1] 空间内。
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;
// ...
【讨论】:
以上是关于在 Three.Js 中剪裁一个体积,给出黑色区域而不是内部材质的主要内容,如果未能解决你的问题,请参考以下文章
Three.js 为啥带有视口和剪刀的渲染器和我有一个完整的黑色画布
使用vue学习three.js之渲染后期处理-使用VignetteShader定制效果添加晕映效果,在图片周围显示黑色边框