体积渲染

渲染体积对象。

体积渲染 展示了如何使用 QCustom3DVolume 来显示体积数据。

运行示例

要从 Qt Creator 运行示例,打开 欢迎 模式并从 示例 中选择示例。有关更多信息,请访问 构建和运行示例

初始化体积项

QCustom3DVolume 项是特殊的自定义项(见 QCustom3DItem),可以用来显示体积数据。体积项仅支持正交投影,因此首先确保图形正在使用它

m_graph->setOrthoProjection(true);

创建一个与坐标轴数据范围相关的体积项

m_volumeItem = new QCustom3DVolume;
// Adjust water level to zero with a minor tweak to y-coordinate position and scaling
m_volumeItem->setScaling(
            QVector3D(m_graph->axisX()->max() - m_graph->axisX()->min(),
                      (m_graph->axisY()->max() - m_graph->axisY()->min()) * 0.91f,
                      m_graph->axisZ()->max() - m_graph->axisZ()->min()));
m_volumeItem->setPosition(
            QVector3D((m_graph->axisX()->max() + m_graph->axisX()->min()) / 2.0f,
                      -0.045f * (m_graph->axisY()->max() - m_graph->axisY()->min()) +
                      (m_graph->axisY()->max() + m_graph->axisY()->min()) / 2.0f,
                      (m_graph->axisZ()->max() + m_graph->axisZ()->min()) / 2.0f));
m_volumeItem->setScalingAbsolute(false);

通过将 QCustom3DItem::scalingAbsolute 属性设置为 false 来指示体积的缩放应随数据范围的改变而改变。接下来,定义体积的内部内容

m_volumeItem->setTextureWidth(lowDetailSize);
m_volumeItem->setTextureHeight(lowDetailSize / 2);
m_volumeItem->setTextureDepth(lowDetailSize);
m_volumeItem->setTextureFormat(QImage::Format_Indexed8);
m_volumeItem->setTextureData(new QList<uchar>(*m_lowDetailData));

为了纹理,使用八位索引颜色,因为它紧凑且易于调整颜色,而无需重新设置整个纹理。对于纹理数据,使用之前基于高度图创建的数据。通常,体积项的数据以图像栈的形式预先生成,因此可以跳过数据生成细节。有关实际数据生成过程的信息,请参阅示例代码。

由于使用了八位索引颜色,需要颜色表来将八位颜色索引映射到实际颜色。在典型用例中,会从源图像中获取颜色表,而不是手动定义一个

m_volumeItem->setColorTable(m_colorTable1);

为了有选项显示围绕体积的切片框架,初始化它们的属性。最初,框架将被隐藏

m_volumeItem->setSliceFrameGaps(QVector3D(0.01f, 0.02f, 0.01f));
m_volumeItem->setSliceFrameThicknesses(QVector3D(0.0025f, 0.005f, 0.0025f));
m_volumeItem->setSliceFrameWidths(QVector3D(0.0025f, 0.005f, 0.0025f));
m_volumeItem->setDrawSliceFrames(false);

最后,将体积作为自定义项添加到图形中以便显示它

m_graph->addCustomItem(m_volumeItem);

在体积中进行切片

除非体积大部分是透明的,否则只能看到其表面,这通常不是很有帮助。查看体积的内部结构的一种方法是通过查看体积的切片。QCustom3DVolume 提供了两种显示切片的方法。第一种方法是将选定的切片显示在体积的位置。例如,要指定垂直于 X 轴的切片,请使用以下方法

m_volumeItem->setSliceIndexX(m_sliceIndexX);

要显示上述指定的切片,必须将 QCustom3DVolume::drawSlices 属性也设置

m_volumeItem->setDrawSlices(true);

查看切片的第二种方法是使用QCustom3DVolume::renderSlice() 方法,该方法将指定的切片生成一个 QImage。然后这个图像可以在另一个小部件上显示,例如一个QLabel

m_sliceLabelX->setPixmap(
            QPixmap::fromImage(m_volumeItem->renderSlice(Qt::XAxis, m_sliceIndexX)));

调整体积透明度

有时,仅仅查看切片并不能很好地理解体积的内部结构。QCustom3DVolume 提供两个可以用来调整体积透明度的属性

m_volumeItem->setAlphaMultiplier(mult);
    ...
m_volumeItem->setPreserveOpacity(enabled);

QCustom3DVolume::alphaMultiplier 是一个应用于体积中每个体素alpha值的一般乘数。这使得为已经稍微透明的体积部分添加均匀的透明度成为可能,以揭示内部的非透明细节。除非将 QCustom3DVolume::preserveOpacity 属性设置为 false,否则此乘数不会影响全不透明的颜色。

调整体积透明度的另一种方法是直接调整体素的alpha值。对于八位索引纹理,这可以通过修改和重置颜色表来实现

int newAlpha = enabled ? terrainTransparency : 255;
for (int i = aboveWaterGroundColorsMin; i < underWaterGroundColorsMax; i++) {
    QRgb oldColor1 = m_colorTable1.at(i);
    QRgb oldColor2 = m_colorTable2.at(i);
    m_colorTable1[i] = qRgba(qRed(oldColor1), qGreen(oldColor1), qBlue(oldColor1), newAlpha);
    m_colorTable2[i] = qRgba(qRed(oldColor2), qGreen(oldColor2), qBlue(oldColor2), newAlpha);
}
if (m_usingPrimaryTable)
    m_volumeItem->setColorTable(m_colorTable1);
else
    m_volumeItem->setColorTable(m_colorTable2);

高清晰度与低清晰度着色器

默认情况下,体积渲染使用高清晰度着色器。它在体素追踪体积内容时为每个体素提供正确的权重,从而提供体积细节的精确表示。然而,这计算成本非常高,因此帧率会受到影响。如果渲染速度比体积内容的像素完美精度更重要,可以将QCustom3DVolume::useHighDefShader 属性设置为 false 使用更快的低清晰度着色器。低清晰度着色器通过在某些精度上做出妥协来提高速度,因此它不保证采样体积的每个体素。这可能导致体积细部上的闪烁或其他渲染错误。

m_volumeItem->setUseHighDefShader(enabled);

示例内容

示例项目 @ code.qt.io

© 2024 The Qt Company Ltd。本文件中包含的文档贡献的版权属于其各自的拥有者。本文件中提供的文档是根据自由软件基金会发布的 GNU自由文档许可协议版本1.3 的条款许可的。Qt及其相关标志是芬兰和/或其他国家和地区 The Qt Company Ltd. 的商标。所有其他商标是其各自所有者的财产。