更改VTK的不透明对象渲染顺序 (Z-顺序)

1 投票
1 回答
1622 浏览
提问于 2025-04-17 23:02

我想找到一种方法来控制多个物体(比如X光图像或三维图像)在同一个Z平面上的渲染顺序。现在我在考虑是否可以在自定义的OpaquePass中重新排列PropArray,但我想知道有没有其他人有更简单的方法来处理这个问题。可惜的是,虽然Image2D有SetDisplayLocationToForeground/BackGround()这个方法,但我不能使用它。

有没有比自己写渲染代码和使用自定义OpaquePass更简单的方法呢?使用这个软件的人可以通过bringToFront/Back的控制来改变X光的渲染顺序。

我已经在WebGL和Three.js中成功测试了这个功能,这两个工具可以控制渲染顺序。比如:在这里输入图片描述

注意:我使用的是Python(2.7.5)和Python Vtk:5.10.1

1 个回答

2

经过一个月的开发和调试,我终于解决了问题!

下面是我如何解决VTK中的渲染深度问题的。

注意:这个方法只会解决在同一z深度上的物体的渲染深度。前面或后面的物体会正常绘制,尽管它们有渲染深度。

逻辑

我们将编辑vtkRenderer的viewProps对象中的绘制顺序。所有渲染深度为null的vtk对象会先绘制,然后是按渲染深度降序排列的对象。

示例:
未排序的渲染深度
viewProps = [ NULL, 3, NULL, 1, 2, 4, NULL]

排序后的渲染深度
viewProps = [ NULL, NULL, NULL, 4, 3, 2, 1]

实现

给vtkObject添加一个叫“renderDepth”的属性,并提供获取和设置的方法。在创建vtkObject时,将renderDepth = NULL;

在vtkRenderer中创建一个方法(我称之为RenderDepthSort)。

递归调用viewProp对象树,然后用简单的冒泡排序交换任何具有渲染深度的项目。

vtkRenderer::RenderDepthSort(vtkPropCollection * propArray){ propArray->InitTraversal(); for(int i=0; i < propArray->GetNumberOfItems(); i++){ vtkProp * prop = propArray->GetNextProp(); if(prop->IsA("vtkAssembly")){ vtkAssembly * ptr = static_cast<vtkAssembly *>(prop); if(ptr->GetParts()->GetNumberOfItems() > 0) this->RenderDepthSort(ptr->GetParts()); } } bool isUnsorted = true; while(isUnsorted){ isUnsorted = false; propArray->InitTraversal(); for(int i=0; i < propArray->GetNumberOfItems()-1; i++){ vtkProp * propA = propArray->GetNextProp(); vtkProp * propB = static_cast<vtkProp *>(propArray->GetItemAsObject(i+1));

  if(propA->GetRenderDepth() == NULL || propB->GetRenderDepth() == NULL){
    if(propA->GetRenderDepth() != NULL && propB->GetRenderDepth() == NULL){
      propArray->ReplaceItem(i, propB);
      propArray->ReplaceItem(i+1, propA);
      isUnsorted = true;
    }
  }else if(propA->GetRenderDepth() < propB->GetRenderDepth()){
    propArray->ReplaceItem(i, propB);
    propArray->ReplaceItem(i+1, propA);
    isUnsorted = true;
  }
} //end for loop

} // 结束while循环 }//结束renderDepthSort方法

如果你像我们一样抽象了你的vtk实现,并且没有完全控制你的vtkViewProps,那么可以实现另一个方法来解决渲染深度并向上传播。

void vtkRenderer::InitSolveRenderDepths(vtkPropCollection * propArray){ int depth = NULL; int numDepths = 0; propArray->InitTraversal(); for(int i=0; i < propArray->GetNumberOfItems(); i++){ vtkProp * prop = propArray->GetNextProp(); if(prop->IsA("vtkAssembly")){ this->SolveRenderDepths(prop); int temp = prop->GetRenderDepth(); if(temp != NULL){ if(temp < depth || depth == NULL){ depth = temp; } numDepths++; } } } }

最后
再创建一个方法叫UpdateDrawOrder()
void vtkRenderer::UpdateDrawOrder(){ vtkPropCollection * props = this->GetViewProps(); this->InitSolveRenderDepths(props); this->RenderDepthSort(props); }

将这个方法设置为在vtkRenderer::Render()或你的vtkRenderer对象中调用UpdateDrawOrder。

结束!

撰写回答