体渲染

渲染体对象。

体渲染展示了如何使用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 Qt公司。本文件中包含的文档贡献者是各自版权的所有者。本文件提供的文档是根据由自由软件基金会发布的 GNU自由文档许可协议版本1.3 的条款提供的。Qt和相关标志是芬兰的Qt公司及其全球子公司和分支机构的商标。所有其他商标是各自所有者的财产。