[英]Three.js: 3D texture MIP depth face clipping when using a perspective camera
我正在为我的一个光模拟器使用 three.js 开发 web GUI。 GUI 需要渲染一个 3D 体积(整数或浮点数),所以我改编了3D 纹理演示脚本并制作了一个测试页面。
经过一些调整,我能够以 MIP 样式渲染 3D 纹理,但显示在正确渲染深度方面似乎存在一些问题 - 某些边界框面可能会在某些摄像机角度消失,并使渲染不准确。
下面的屏幕截图显示了问题。 纹理是具有两个 z 层的 40x20x30 体积:0<z<20 的值为 1.0,20<z<30 的值为 2.0。
从上面的屏幕截图中可以看出,MIP 渲染在左视角还可以,但在大多数其他角度开始显示锯齿状边界(或缺少 bbx 面),如右侧所示。
您可以点击以下链接自行查看
http://mcx.space/test/0235423747321423142346464758/
要输入此体积,请单击“JSON”选项卡,删除现有文本,然后复制/粘贴以下 JSON 数据(如您所见,“形状”object 定义了 Z76AA96369ABBBA52E621BFA83DA86 格式的 Z76AA96369ABBBA52E621BFA83DA86 数组被解码为一个numjs NdArray对象)。 替换 JSON 文本后,您可以单击“预览”选项卡查看渲染。
{
"Session": {
"ID": "mcx",
"Photons": 100000,
"DoMismatch": true,
"DoAutoThread": true,
"DoSaveVolume": true,
"DoPartialPath": true,
"DoNormalize": true,
"DoSaveRef": false,
"DoSaveExit": false,
"DoSaveSeed": false,
"DoDCS": false,
"DoSpecular": true,
"DebugFlag": "",
"SaveDataMask": "DP",
"OutputFormat": "nii",
"OutputType": "x",
"RNGSeed": 1648335518
},
"Forward": {
"T0": 0,
"T1": 5e-9,
"Dt": 5e-9
},
"Optode": {
"Source": {
"Type": "pencil",
"Pos": [30,30,0],
"Dir": [0,0,1],
"Param1": [0,0,0,0],
"Param2": [0,0,0,0]
},
"Detector": []
},
"Shapes":{
"_ArrayType_":"uint8",
"_ArraySize_":[40,20,30],
"_ArrayZipType_":"zlib",
"_ArrayZipSize_":24000,
"_ArrayZipData_":"eJztybENAAAIA6DU/492dOgHBlaSMqfTWmuttdZaa6211lprrbXWWmuttdZaa6211lprrbXWWmuttdZaa6211lprrbXWWmuttdZaa6211lprv+4CkyqAIQ=="
},
"Domain": {
"OriginType": true,
"Dim": [60,60,60],
"VolumeFile": "",
"Media": [
{
"mua": 0,
"mus": 0,
"g": 1,
"n": 1
},
{
"mua": 0,
"mus": 0,
"g": 1,
"n": 1
}
]
}
}
我的脚本主要改编自 3d 纹理演示。 我尝试在材质设置中添加transparent: true, opacity: 0.6, alphaTest: 0.5, depthWrite: false
,但没有任何区别。
因为我的数据和演示脚本是同一个 float32 数组,但是演示脚本在 MIP 模式下运行得非常好。 我想知道我是否忽略了一些东西。
非常感谢您的评论和指点! 谢谢
function render(){
renderer.render( scene, camera );
}
function drawvolume(volume){
const dtype={
uint8:THREE.UnsignedByteType,
uint16:THREE.UnsignedShortType,
uint32:THREE.UnsignedIntType,
int8:THREE.ByteType,
int16:THREE.ShortType,
int32:THREE.IntType,
float32:THREE.FloatType
};
const dim=volume.shape;
const buf=nj.array(volume.flatten().selection.data, 'float32');//had to cast to float32, otherwise, uint8 won't render
const texture = new THREE.DataTexture3D( buf.selection.data, dim[2], dim[1], dim[0]);
texture.format = THREE.RedFormat;
texture.type = THREE.FloatType;
texture.minFilter = texture.magFilter = THREE.LinearFilter;
texture.unpackAlignment = 1;
// Colormap textures
const cmtextures = {
viridis: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/cm_viridis.png', render ),
gray: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/cm_gray.png', render )
};
// Material
const shader = VolumeRenderShader1;
const uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms[ "u_data" ].value = texture;
uniforms[ "u_size" ].value.set( dim[2], dim[1], dim[0] );
uniforms[ "u_clim" ].value.set( volume.min(), volume.max() );
uniforms[ "u_renderstyle" ].value = 0;
uniforms[ "u_renderthreshold" ].value = 0.2;
uniforms[ "u_cmdata" ].value = cmtextures[ "viridis" ];
const material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader,
side: THREE.BackSide // The volume shader uses the backface as its "reference point"
} );
// THREE.Mesh
const geometry = new THREE.BoxGeometry( dim[2], dim[1], dim[0] );
geometry.translate(dim[2]*0.5 - 0.5, dim[1]*0.5 - 0.5, dim[0]*0.5 - 0.5 );
const mesh = new THREE.Mesh( geometry, material );
return mesh;
}
...
if(isWebGL2Available()){
let jd=new jdata(cfg.Shapes,{});
let vol=jd.decode().data;
boundingbox.add( drawvolume(vol.transpose()) );
}
另外一个问题:我也无法渲染 3D integer 数组而不是浮点数组。 我尝试将纹理设置更新为以下内容,但它显示了一个统一的块。 我怀疑我还需要编写一个新的着色器?
const texture = new THREE.DataTexture3D( volume.selection.data, dim[2], dim[1], dim[0]);
texture.format = THREE.RedIntegerFormat;
texture.type = dtype[volume.dtype];
texture.minFilter = texture.magFilter = THREE.LinearFilter;
texture.unpackAlignment = 1;
我不确定我是否解决了您的问题。 对我来说,这看起来像是材料应用的一面的问题。 也许您应该在ShaderMaterial
中尝试THREE.DoubleSide
或THREE.FrontSide
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.