mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-23 15:06:32 +00:00
Mesh exploder
New 'Exploded' visualisation mode in BufferViewer with new exploder controls hidden when not in 'Exploded' mode. Change 'solidShading' and 'solidShadeMode' to 'visualisation' and 'visualisationMode'. Hide the 'highlightVerts' widget when using 'Exploded' vis for both real-estate and practical implementation reasons.
This commit is contained in:
committed by
Baldur Karlsson
parent
da3e2366ac
commit
442b48bb77
@@ -184,7 +184,7 @@ More details can be found on the :doc:`../window/mesh_viewer` page.
|
||||
|
||||
Mesh Viewer allows you to inspect the geometry data as it passes through the pipeline. Both raw data in a grid view and 3D inspection is possible. The tabs in the preview window allow you to choose at which part of the pipeline you'd like to visualise the data.
|
||||
|
||||
By default the preview shows a wireframe rendering of the mesh, but you can choose solid shading options. This can either be simple shading or use a secondary attribute as color. Right clicking on any column allows you to choose the secondary attribute for rendering.
|
||||
By default the preview shows a wireframe rendering of the mesh, but you can choose different visualisations. This can either be simple shading, a vertex exploder utility, or using a secondary attribute as color. Right clicking on any column allows you to choose the secondary attribute for rendering.
|
||||
|
||||
You can also select which attribute is the position, in case either the auto-detection failed or you want to visualise another attribute like texture co-ordinates in 3D space.
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
@@ -61,7 +61,7 @@ Mesh View
|
||||
.. autoclass:: MeshFormat
|
||||
:members:
|
||||
|
||||
.. autoclass:: SolidShade
|
||||
.. autoclass:: Visualisation
|
||||
:members:
|
||||
|
||||
.. autoclass:: Camera
|
||||
|
||||
@@ -47,12 +47,21 @@ Page up and Page down will move vertically 'up' and 'down' relative to the camer
|
||||
Mesh Preview
|
||||
------------
|
||||
|
||||
In the 3D Mesh preview, you have the option to display the mesh with some solid shading modes, not just as a wireframe mesh. When solid shading you can toggle the wireframe on and off.
|
||||
In the 3D Mesh preview, you have the option to display the mesh with some colored visualisations, not just as a wireframe mesh. When using one of the visualisations, you can toggle the wireframe on and off.
|
||||
|
||||
* Solid Color simply displays a solid color for each triangle.
|
||||
* Flat Shaded will perform basic flat lighting calculations based on triangle normals to give a better idea of the topology of the mesh.
|
||||
* Secondary will display the selected secondary mesh element.
|
||||
* Meshlet is only relevant when using mesh shaders, and will colourise each meshlet with a different colour.
|
||||
* Exploded will display a shaded mesh where vertex colors are a function of the vertex index (SV_VertexID or gl_VertexID). This means adjacent primitives that do not share the exact same vertices can be more easily seen by a hard break in coloring. Additionally, a slider allows displacing vertices along an explosion direction by an amount based on the vertex index, which also helps better visualise shared or disjoint vertices and can also help in visualising other mesh problems (e.g. hidden or duplicate vertices/primitives).
|
||||
|
||||
.. figure:: ../imgs/Screenshots/ExploderBadShoes.png
|
||||
|
||||
Exploded: Visualising a mesh with no vertex sharing.
|
||||
|
||||
.. figure:: ../imgs/Screenshots/ExploderGoodShoes.png
|
||||
|
||||
Exploded: Visualising a mesh with widely shared vertices.
|
||||
|
||||
To select which element will be displayed as secondary, simply right click on the column you would like to use. This can be done on the input and output separately, and 4-component columns have the option to either show RGB as color, or alpha as grayscale.
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
|
||||
namespace Constants
|
||||
{
|
||||
static const int SliderHandleHalfWidth = 4;
|
||||
static const int SliderGrooveHeight = 4;
|
||||
|
||||
static const int ButtonMargin = 6;
|
||||
static const int ButtonBorder = 1;
|
||||
|
||||
@@ -470,6 +473,32 @@ QRect RDStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
|
||||
|
||||
return opt->rect;
|
||||
}
|
||||
else if(cc == QStyle::CC_Slider)
|
||||
{
|
||||
QRect ret = opt->rect;
|
||||
ret.adjust(1, 1, -1, -1);
|
||||
if(sc == QStyle::SC_SliderGroove)
|
||||
{
|
||||
int toGrooveHeightHalfReduction = (ret.height() - Constants::SliderGrooveHeight) / 2;
|
||||
ret.adjust(Constants::SliderHandleHalfWidth, toGrooveHeightHalfReduction,
|
||||
-Constants::SliderHandleHalfWidth, -toGrooveHeightHalfReduction);
|
||||
}
|
||||
else if(sc == QStyle::SC_SliderHandle)
|
||||
{
|
||||
const QAbstractSlider *slider = qobject_cast<const QAbstractSlider *>(widget);
|
||||
int sliderMin = slider->minimum();
|
||||
int sliderMax = slider->maximum();
|
||||
int sliderPos = slider->sliderPosition();
|
||||
qreal posUNorm = (qreal)(sliderPos - sliderMin) / (qreal)(sliderMax - sliderMin);
|
||||
int grooveLeft = ret.left() + Constants::SliderHandleHalfWidth;
|
||||
int grooveRight = ret.right() - Constants::SliderHandleHalfWidth;
|
||||
int grooveWidth = grooveRight - grooveLeft;
|
||||
int sliderX = (int)(posUNorm * (qreal)grooveWidth) + grooveLeft;
|
||||
ret.setLeft(sliderX - Constants::SliderHandleHalfWidth);
|
||||
ret.setRight(sliderX + Constants::SliderHandleHalfWidth);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else if(cc == QStyle::CC_ComboBox)
|
||||
{
|
||||
QRect rect = opt->rect;
|
||||
@@ -1118,6 +1147,19 @@ void RDStyle::drawComplexControl(ComplexControl control, const QStyleOptionCompl
|
||||
|
||||
return;
|
||||
}
|
||||
else if(control == QStyle::CC_Slider)
|
||||
{
|
||||
QRect grooveRect = subControlRect(control, opt, QStyle::SC_SliderGroove, widget);
|
||||
p->drawLine(QLine(grooveRect.x(), grooveRect.y() + grooveRect.height() / 2, grooveRect.right(),
|
||||
grooveRect.y() + grooveRect.height() / 2));
|
||||
|
||||
QRect handleRect = subControlRect(control, opt, QStyle::SC_SliderHandle, widget);
|
||||
QBrush handleBrush = (m_Scheme == Light) ? opt->palette.brush(QPalette::Dark)
|
||||
: opt->palette.brush(QPalette::Text);
|
||||
p->fillRect(handleRect, handleBrush);
|
||||
|
||||
return;
|
||||
}
|
||||
else if(control == QStyle::CC_ComboBox)
|
||||
{
|
||||
const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt);
|
||||
|
||||
@@ -2402,6 +2402,7 @@ BufferViewer::BufferViewer(ICaptureContext &ctx, bool meshview, QWidget *parent)
|
||||
memset(&m_Config, 0, sizeof(m_Config));
|
||||
m_Config.type = MeshDataStage::VSIn;
|
||||
m_Config.wireframeDraw = true;
|
||||
m_Config.exploderScale = 1.0f;
|
||||
|
||||
ui->outputTabs->setCurrentIndex(0);
|
||||
m_CurStage = MeshDataStage::VSIn;
|
||||
@@ -2537,10 +2538,11 @@ BufferViewer::BufferViewer(ICaptureContext &ctx, bool meshview, QWidget *parent)
|
||||
|
||||
configureDrawRange();
|
||||
|
||||
ui->solidShading->clear();
|
||||
ui->solidShading->addItems({tr("None"), tr("Solid Colour"), tr("Flat Shaded"), tr("Secondary")});
|
||||
ui->solidShading->adjustSize();
|
||||
ui->solidShading->setCurrentIndex(0);
|
||||
ui->visualisation->clear();
|
||||
ui->visualisation->addItems(
|
||||
{tr("None"), tr("Solid Colour"), tr("Flat Shaded"), tr("Secondary"), tr("Exploded")});
|
||||
ui->visualisation->adjustSize();
|
||||
ui->visualisation->setCurrentIndex(0);
|
||||
|
||||
ui->matrixType->addItems({tr("Perspective"), tr("Orthographic")});
|
||||
|
||||
@@ -2843,7 +2845,7 @@ void BufferViewer::SetupMeshView()
|
||||
BufferItemModel *model = (BufferItemModel *)m_CurView->model();
|
||||
|
||||
model->setPosColumn(-1);
|
||||
model->setSecondaryColumn(-1, m_Config.solidShadeMode == SolidShade::Secondary, false);
|
||||
model->setSecondaryColumn(-1, m_Config.visualisationMode == Visualisation::Secondary, false);
|
||||
|
||||
UI_ConfigureFormats();
|
||||
on_resetCamera_clicked();
|
||||
@@ -2863,8 +2865,8 @@ void BufferViewer::SetupMeshView()
|
||||
QObject::connect(m_SelectSecondColumn, &QAction::triggered, [this]() {
|
||||
BufferItemModel *model = (BufferItemModel *)m_CurView->model();
|
||||
|
||||
model->setSecondaryColumn(m_ContextColumn, m_Config.solidShadeMode == SolidShade::Secondary,
|
||||
false);
|
||||
model->setSecondaryColumn(m_ContextColumn,
|
||||
m_Config.visualisationMode == Visualisation::Secondary, false);
|
||||
|
||||
UI_ConfigureFormats();
|
||||
UpdateCurrentMeshConfig();
|
||||
@@ -2873,8 +2875,8 @@ void BufferViewer::SetupMeshView()
|
||||
QObject::connect(m_SelectSecondAlphaColumn, &QAction::triggered, [this]() {
|
||||
BufferItemModel *model = (BufferItemModel *)m_CurView->model();
|
||||
|
||||
model->setSecondaryColumn(m_ContextColumn, m_Config.solidShadeMode == SolidShade::Secondary,
|
||||
true);
|
||||
model->setSecondaryColumn(m_ContextColumn,
|
||||
m_Config.visualisationMode == Visualisation::Secondary, true);
|
||||
UI_ConfigureFormats();
|
||||
UpdateCurrentMeshConfig();
|
||||
INVOKE_MEMFN(RT_UpdateAndDisplay);
|
||||
@@ -3674,7 +3676,8 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
|
||||
// similarly for secondary columns
|
||||
if(m_ModelIn->secondaryColumn() == -1 ||
|
||||
bufdata->highlightNames[1] != bufdata->inConfig.columnName(m_ModelIn->secondaryColumn()))
|
||||
m_ModelIn->setSecondaryColumn(-1, m_Config.solidShadeMode == SolidShade::Secondary, false);
|
||||
m_ModelIn->setSecondaryColumn(-1, m_Config.visualisationMode == Visualisation::Secondary,
|
||||
false);
|
||||
|
||||
// and as above for VS Out / GS Out
|
||||
if(m_ModelOut1->posColumn() == -1 ||
|
||||
@@ -3682,14 +3685,16 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
|
||||
m_ModelOut1->setPosColumn(-1);
|
||||
if(m_ModelOut1->secondaryColumn() == -1 ||
|
||||
bufdata->highlightNames[3] != bufdata->out1Config.columnName(m_ModelOut1->secondaryColumn()))
|
||||
m_ModelOut1->setSecondaryColumn(-1, m_Config.solidShadeMode == SolidShade::Secondary, false);
|
||||
m_ModelOut1->setSecondaryColumn(-1, m_Config.visualisationMode == Visualisation::Secondary,
|
||||
false);
|
||||
|
||||
if(m_ModelOut2->posColumn() == -1 ||
|
||||
bufdata->highlightNames[4] != bufdata->out2Config.columnName(m_ModelOut2->posColumn()))
|
||||
m_ModelOut2->setPosColumn(-1);
|
||||
if(m_ModelOut2->secondaryColumn() == -1 ||
|
||||
bufdata->highlightNames[5] != bufdata->out2Config.columnName(m_ModelOut2->secondaryColumn()))
|
||||
m_ModelOut2->setSecondaryColumn(-1, m_Config.solidShadeMode == SolidShade::Secondary, false);
|
||||
m_ModelOut2->setSecondaryColumn(-1, m_Config.visualisationMode == Visualisation::Secondary,
|
||||
false);
|
||||
|
||||
EnableCameraGuessControls();
|
||||
|
||||
@@ -5306,9 +5311,9 @@ void BufferViewer::updateLabelsAndLayout()
|
||||
ui->outputTabs->setTabText(0, tr("Mesh Input"));
|
||||
ui->outputTabs->setTabText(1, tr("Mesh Out"));
|
||||
|
||||
if(ui->solidShading->itemText(ui->solidShading->count() - 1) != tr("Meshlet"))
|
||||
ui->solidShading->addItem(tr("Meshlet"));
|
||||
ui->solidShading->adjustSize();
|
||||
if(ui->visualisation->itemText(ui->visualisation->count() - 1) != tr("Meshlet"))
|
||||
ui->visualisation->addItem(tr("Meshlet"));
|
||||
ui->visualisation->adjustSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5334,9 +5339,9 @@ void BufferViewer::updateLabelsAndLayout()
|
||||
ui->outputTabs->setTabText(1, tr("VS Out"));
|
||||
ui->outputTabs->setTabText(2, tr("GS/DS Out"));
|
||||
|
||||
if(ui->solidShading->itemText(ui->solidShading->count() - 1) == tr("Meshlet"))
|
||||
ui->solidShading->removeItem(ui->solidShading->count() - 1);
|
||||
ui->solidShading->adjustSize();
|
||||
if(ui->visualisation->itemText(ui->visualisation->count() - 1) == tr("Meshlet"))
|
||||
ui->visualisation->removeItem(ui->visualisation->count() - 1);
|
||||
ui->visualisation->adjustSize();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -5363,9 +5368,9 @@ void BufferViewer::updateLabelsAndLayout()
|
||||
ui->outputTabs->setTabText(1, tr("VS Out"));
|
||||
ui->outputTabs->setTabText(2, tr("GS/DS Out"));
|
||||
|
||||
if(ui->solidShading->itemText(ui->solidShading->count() - 1) == tr("Meshlet"))
|
||||
ui->solidShading->removeItem(ui->solidShading->count() - 1);
|
||||
ui->solidShading->adjustSize();
|
||||
if(ui->visualisation->itemText(ui->visualisation->count() - 1) == tr("Meshlet"))
|
||||
ui->visualisation->removeItem(ui->visualisation->count() - 1);
|
||||
ui->visualisation->adjustSize();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -6678,7 +6683,7 @@ void BufferViewer::UpdateHighlightVerts()
|
||||
{
|
||||
m_Config.highlightVert = ~0U;
|
||||
|
||||
if(!ui->highlightVerts->isChecked())
|
||||
if(ui->highlightVerts->isHidden() || !ui->highlightVerts->isChecked())
|
||||
return;
|
||||
|
||||
RDTableView *table = currentTable();
|
||||
@@ -6777,6 +6782,25 @@ void BufferViewer::on_highlightVerts_toggled(bool checked)
|
||||
INVOKE_MEMFN(RT_UpdateAndDisplay);
|
||||
}
|
||||
|
||||
void BufferViewer::on_vtxExploderSlider_valueChanged(int value)
|
||||
{
|
||||
m_Config.vtxExploderSliderSNorm = (float)value / 100.0f;
|
||||
|
||||
INVOKE_MEMFN(RT_UpdateAndDisplay);
|
||||
}
|
||||
|
||||
void BufferViewer::on_exploderReset_clicked()
|
||||
{
|
||||
ui->vtxExploderSlider->setSliderPosition(0);
|
||||
}
|
||||
|
||||
void BufferViewer::on_exploderScale_valueChanged(double value)
|
||||
{
|
||||
m_Config.exploderScale = (float)value;
|
||||
|
||||
INVOKE_MEMFN(RT_UpdateAndDisplay);
|
||||
}
|
||||
|
||||
void BufferViewer::on_wireframeRender_toggled(bool checked)
|
||||
{
|
||||
m_Config.wireframeDraw = checked;
|
||||
@@ -6784,7 +6808,7 @@ void BufferViewer::on_wireframeRender_toggled(bool checked)
|
||||
INVOKE_MEMFN(RT_UpdateAndDisplay);
|
||||
}
|
||||
|
||||
void BufferViewer::on_solidShading_currentIndexChanged(int index)
|
||||
void BufferViewer::on_visualisation_currentIndexChanged(int index)
|
||||
{
|
||||
ui->wireframeRender->setEnabled(index > 0);
|
||||
|
||||
@@ -6794,16 +6818,31 @@ void BufferViewer::on_solidShading_currentIndexChanged(int index)
|
||||
m_Config.wireframeDraw = true;
|
||||
}
|
||||
|
||||
m_Config.solidShadeMode = (SolidShade)qMax(0, index);
|
||||
bool explodeHidden = (index != (int)Visualisation::Explode);
|
||||
ui->vtxExploderLabel->setHidden(explodeHidden);
|
||||
ui->vtxExploderSlider->setHidden(explodeHidden);
|
||||
ui->exploderReset->setHidden(explodeHidden);
|
||||
ui->exploderScaleLabel->setHidden(explodeHidden);
|
||||
ui->exploderScale->setHidden(explodeHidden);
|
||||
// Because the vertex/prim highlights draw from a new, temporary vertex buffer,
|
||||
// those vertex IDs (which determine the explode displacement) won't necessarily
|
||||
// match the original mesh's IDs and exploded vertices. Because of this, it seems
|
||||
// cleanest to just avoid drawing the highlighted vert/prim with the explode
|
||||
// visualisation (while also getting back a little room on the toolbar used by
|
||||
// the extra exploder controls).
|
||||
ui->highlightVerts->setHidden(!explodeHidden);
|
||||
UpdateHighlightVerts();
|
||||
|
||||
m_Config.visualisationMode = (Visualisation)qMax(0, index);
|
||||
|
||||
m_ModelIn->setSecondaryColumn(m_ModelIn->secondaryColumn(),
|
||||
m_Config.solidShadeMode == SolidShade::Secondary,
|
||||
m_Config.visualisationMode == Visualisation::Secondary,
|
||||
m_ModelIn->secondaryAlpha());
|
||||
m_ModelOut1->setSecondaryColumn(m_ModelOut1->secondaryColumn(),
|
||||
m_Config.solidShadeMode == SolidShade::Secondary,
|
||||
m_Config.visualisationMode == Visualisation::Secondary,
|
||||
m_ModelOut1->secondaryAlpha());
|
||||
m_ModelOut2->setSecondaryColumn(m_ModelOut2->secondaryColumn(),
|
||||
m_Config.solidShadeMode == SolidShade::Secondary,
|
||||
m_Config.visualisationMode == Visualisation::Secondary,
|
||||
m_ModelOut2->secondaryAlpha());
|
||||
|
||||
INVOKE_MEMFN(RT_UpdateAndDisplay);
|
||||
|
||||
@@ -128,8 +128,11 @@ private slots:
|
||||
void on_showPadding_toggled(bool checked);
|
||||
void on_resourceDetails_clicked();
|
||||
void on_highlightVerts_toggled(bool checked);
|
||||
void on_vtxExploderSlider_valueChanged(int value);
|
||||
void on_exploderReset_clicked();
|
||||
void on_exploderScale_valueChanged(double value);
|
||||
void on_wireframeRender_toggled(bool checked);
|
||||
void on_solidShading_currentIndexChanged(int index);
|
||||
void on_visualisation_currentIndexChanged(int index);
|
||||
void on_drawRange_currentIndexChanged(int index);
|
||||
void on_controlType_currentIndexChanged(int index);
|
||||
void on_camSpeed_valueChanged(double value);
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>788</width>
|
||||
<height>537</height>
|
||||
<width>1300</width>
|
||||
<height>837</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -307,14 +307,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="solidShadingLabel">
|
||||
<widget class="QLabel" name="visualisationLabel">
|
||||
<property name="text">
|
||||
<string>Solid Shading</string>
|
||||
<string>Visualisation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="solidShading"/>
|
||||
<widget class="QComboBox" name="visualisation"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="wireframeRender">
|
||||
@@ -382,6 +382,131 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="vtxExploderLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exploder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="vtxExploderSlider">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>90</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::NoContextMenu</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Explode vertices</string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>slider name</string>
|
||||
</property>
|
||||
<property name="accessibleDescription">
|
||||
<string>slider description</string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="invertedControls">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::NoTicks</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exploderReset">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reset/zero exploder slider</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="exploderScaleLabel">
|
||||
<property name="text">
|
||||
<string>Scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="exploderScale">
|
||||
<property name="toolTip">
|
||||
<string>Exploder scaling</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -309,10 +309,15 @@ struct MeshDisplay
|
||||
DOCUMENT("``True`` if the bounding box around the mesh should be rendered.");
|
||||
bool showBBox = false;
|
||||
|
||||
DOCUMENT("The :class:`solid shading mode <SolidShade>` to use when rendering the current mesh.");
|
||||
SolidShade solidShadeMode = SolidShade::NoSolid;
|
||||
DOCUMENT(
|
||||
"The :class:`visualisation mode <Visualisation>` to use when rendering the current mesh.");
|
||||
Visualisation visualisationMode = Visualisation::NoSolid;
|
||||
DOCUMENT("``True`` if the wireframe of the mesh should be rendered as well as solid shading.");
|
||||
bool wireframeDraw = true;
|
||||
DOCUMENT("Displace/explode vertices to help visualise vertex reuse vs disjointedness.");
|
||||
float vtxExploderSliderSNorm = 0.0f;
|
||||
DOCUMENT("Scales the exploded vertex displacement.");
|
||||
float exploderScale = 1.0f;
|
||||
|
||||
static const uint32_t NoHighlight = ~0U;
|
||||
};
|
||||
|
||||
@@ -2895,7 +2895,7 @@ constexpr inline ResourceUsage RWResUsage(ShaderStage stage)
|
||||
return RWResUsage(uint32_t(stage));
|
||||
}
|
||||
|
||||
DOCUMENT(R"(What kind of solid shading to use when rendering a mesh.
|
||||
DOCUMENT(R"(What kind of visualisation to use when rendering a mesh.
|
||||
|
||||
.. data:: NoSolid
|
||||
|
||||
@@ -2913,22 +2913,27 @@ DOCUMENT(R"(What kind of solid shading to use when rendering a mesh.
|
||||
|
||||
The mesh should be rendered using the secondary element as color.
|
||||
|
||||
.. data:: Explode
|
||||
|
||||
The mesh should be rendered with vertices displaced and coloured by vertex ID.
|
||||
|
||||
.. data:: Meshlet
|
||||
|
||||
The mesh should be rendered colorising each meshlet differently.
|
||||
|
||||
)");
|
||||
enum class SolidShade : uint32_t
|
||||
enum class Visualisation : uint32_t
|
||||
{
|
||||
NoSolid = 0,
|
||||
Solid,
|
||||
Lit,
|
||||
Secondary,
|
||||
Explode,
|
||||
Meshlet,
|
||||
Count,
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_ENUM(SolidShade);
|
||||
DECLARE_REFLECTION_ENUM(Visualisation);
|
||||
|
||||
DOCUMENT(R"(The fill mode for polygons.
|
||||
|
||||
|
||||
@@ -172,14 +172,15 @@ vec3 CalcCubeCoord(vec2 uv, int face)
|
||||
|
||||
#endif
|
||||
|
||||
// first few match SolidShade enum
|
||||
// first few match Visualisation enum
|
||||
#define MESHDISPLAY_SOLID 0x1
|
||||
#define MESHDISPLAY_FACELIT 0x2
|
||||
#define MESHDISPLAY_SECONDARY 0x3
|
||||
#define MESHDISPLAY_MESHLET 0x4
|
||||
#define MESHDISPLAY_EXPLODE 0x4
|
||||
#define MESHDISPLAY_MESHLET 0x5
|
||||
|
||||
// extra values below
|
||||
#define MESHDISPLAY_SECONDARY_ALPHA 0x5
|
||||
#define MESHDISPLAY_SECONDARY_ALPHA 0x6
|
||||
|
||||
#define MAX_NUM_MESHLETS (512 * 1024)
|
||||
|
||||
|
||||
@@ -35,12 +35,19 @@ BINDING(0) uniform MeshUBOData
|
||||
mat4 mvp;
|
||||
mat4 invProj;
|
||||
vec4 color;
|
||||
|
||||
int displayFormat;
|
||||
uint homogenousInput;
|
||||
vec2 pointSpriteSize;
|
||||
|
||||
uint rawoutput;
|
||||
uint flipY;
|
||||
vec2 padding;
|
||||
float vtxExploderSNorm;
|
||||
float exploderScale;
|
||||
|
||||
vec3 exploderCentre;
|
||||
float padding;
|
||||
|
||||
uvec4 meshletColours[12];
|
||||
}
|
||||
INST_NAME(Mesh);
|
||||
|
||||
@@ -60,6 +60,12 @@ void main(void)
|
||||
|
||||
color_out = vec4(Mesh.color.xyz * abs(dot(lightDir, NORM_NAME.xyz)), 1);
|
||||
}
|
||||
else if(type == MESHDISPLAY_EXPLODE)
|
||||
{
|
||||
vec3 lightDir = normalize(vec3(0, -0.3f, -1));
|
||||
|
||||
color_out = vec4(SECONDARY_NAME.xyz * abs(dot(lightDir, NORM_NAME.xyz)), 1);
|
||||
}
|
||||
else // if(type == MESHDISPLAY_SOLID)
|
||||
{
|
||||
color_out = vec4(Mesh.color.xyz, 1);
|
||||
|
||||
@@ -36,6 +36,70 @@
|
||||
#define SECONDARY_TYPE vec4
|
||||
#endif
|
||||
|
||||
// This function is mostly duplicated between 'mesh.hlsl' and 'mesh.vert'.
|
||||
// Without a convenient shared common source, changes to one should be
|
||||
// reflected in the other.
|
||||
void vtxExploder(in int vtxID, inout vec3 pos, inout vec3 secondary)
|
||||
{
|
||||
if(Mesh.exploderScale > 0.0f)
|
||||
{
|
||||
float nonLinearVtxExplodeScale = 4.0f * Mesh.exploderScale * Mesh.vtxExploderSNorm *
|
||||
Mesh.vtxExploderSNorm * Mesh.vtxExploderSNorm;
|
||||
|
||||
// A vertex might be coincident with our 'exploderCentre' so that, when normalized,
|
||||
// can give us INFs/NaNs that, even if multiplied by a zero 'exploderScale', can
|
||||
// leave us with bad numbers (as seems to be the case with glsl/vulkan, but not hlsl).
|
||||
// Still, we should make this case safe for when we have a non-zero 'exploderScale' -
|
||||
vec3 offset = pos - Mesh.exploderCentre;
|
||||
float offsetDistSquared = dot(offset, offset);
|
||||
vec3 safeExplodeDir = offset * inversesqrt(max(offsetDistSquared, FLT_EPSILON));
|
||||
|
||||
float displacement =
|
||||
nonLinearVtxExplodeScale * ((float((vtxID >> 1) & 0xf) / 15.0f) * 1.5f - 0.5f);
|
||||
pos += (safeExplodeDir * displacement);
|
||||
|
||||
// For the exploder visualisation, colour verts based on vertex ID, which we
|
||||
// store in secondary.
|
||||
//
|
||||
// Interpolate a colour gradient from 0.0 to 1.0 and back to 0.0 for vertex IDs
|
||||
// 0 to 16 to 32 respectively -
|
||||
// 1 - | .`.
|
||||
// | .` `.
|
||||
// | .` | `.
|
||||
// 0.5-| .` `.
|
||||
// | .` | `. .
|
||||
// |.` `. .`
|
||||
// 0.0-+-----------+-----------+--- vtx IDs
|
||||
// 0 16 32
|
||||
|
||||
float vtxIDMod32Div16 = float(vtxID % 32) / 16.0f; // 0: 0.0 16: 1.0 31: 1.94
|
||||
float descending = floor(vtxIDMod32Div16); // 0..15: 0.0 16..31: 1.0
|
||||
float gradientVal = abs(vtxIDMod32Div16 - (2.0f * descending)); // 0.0..1.0
|
||||
|
||||
// Use a hopefully fairly intuitive temperature gradient scheme to help visualise
|
||||
// contiguous/nearby sequences of vertices, which should also show up breaks in
|
||||
// colour where verts aren't shared between adjacent primitives.
|
||||
const vec3 gradientColours[5] =
|
||||
vec3[](vec3(0.004f, 0.002f, 0.025f), // 0.0..0.25: Dark blue
|
||||
vec3(0.305f, 0.001f, 0.337f), // 0.25..0.5: Purple
|
||||
vec3(0.665f, 0.033f, 0.133f), // 0.5..0.75: Purple orange
|
||||
vec3(1.000f, 0.468f, 0.000f), // 0.75..1.0: Orange
|
||||
vec3(1.000f, 1.000f, 1.000f) // 1.0: White
|
||||
);
|
||||
|
||||
uint gradientSectionStartIdx = uint(gradientVal * 4.0f);
|
||||
uint gradientSectionEndIdx = min(gradientSectionStartIdx + 1u, 4u);
|
||||
vec3 gradSectionStartCol = gradientColours[gradientSectionStartIdx];
|
||||
vec3 gradSectionEndCol = gradientColours[gradientSectionEndIdx];
|
||||
|
||||
float sectionLerp = gradientVal - float(gradientSectionStartIdx) * 0.25f;
|
||||
vec3 gradCol = mix(gradientColours[gradientSectionStartIdx],
|
||||
gradientColours[gradientSectionEndIdx], sectionLerp);
|
||||
|
||||
secondary = gradCol;
|
||||
}
|
||||
}
|
||||
|
||||
IO_LOCATION(0) in POSITION_TYPE vsin_position;
|
||||
IO_LOCATION(1) in SECONDARY_TYPE vsin_secondary;
|
||||
|
||||
@@ -111,6 +175,9 @@ void main(void)
|
||||
vec2[](vec2(-1.0f, -1.0f), vec2(-1.0f, 1.0f), vec2(1.0f, -1.0f), vec2(1.0f, 1.0f));
|
||||
|
||||
vec4 pos = vec4(vsin_position);
|
||||
vec4 secondary = vec4(vsin_secondary);
|
||||
vtxExploder(VERTEX_ID, pos.xyz, secondary.xyz);
|
||||
|
||||
if(Mesh.homogenousInput == 0u)
|
||||
{
|
||||
pos = vec4(pos.xyz, 1);
|
||||
@@ -124,7 +191,7 @@ void main(void)
|
||||
|
||||
gl_Position = Mesh.mvp * pos;
|
||||
gl_Position.xy += Mesh.pointSpriteSize.xy * 0.01f * psprite[VERTEX_ID % 4] * gl_Position.w;
|
||||
vsout_secondary = vec4(vsin_secondary);
|
||||
vsout_secondary = vec4(secondary);
|
||||
vsout_norm = vec4(0, 0, 1, 1);
|
||||
|
||||
#ifdef VULKAN
|
||||
|
||||
@@ -107,12 +107,15 @@ cbuffer MeshVertexCBuffer REG(b0)
|
||||
|
||||
float2 SpriteSize;
|
||||
uint homogenousInput;
|
||||
uint vertMeshDisplayFormat;
|
||||
float vtxExploderSNorm;
|
||||
|
||||
float3 exploderCentre;
|
||||
float exploderScale; // Non-zero values imply use of the exploder visualisation.
|
||||
|
||||
uint vertMeshDisplayFormat;
|
||||
uint meshletOffset;
|
||||
uint meshletCount;
|
||||
uint padding1;
|
||||
uint padding2;
|
||||
|
||||
uint4 meshletColours[12];
|
||||
};
|
||||
@@ -250,14 +253,15 @@ cbuffer DebugSampleOperation REG(b0)
|
||||
#define RESTYPE_DEPTH_STENCIL_MS 0x7
|
||||
#define RESTYPE_TEX2D_MS 0x9
|
||||
|
||||
// first few match SolidShade enum
|
||||
// first few match Visualisation enum
|
||||
#define MESHDISPLAY_SOLID 0x1
|
||||
#define MESHDISPLAY_FACELIT 0x2
|
||||
#define MESHDISPLAY_SECONDARY 0x3
|
||||
#define MESHDISPLAY_MESHLET 0x4
|
||||
#define MESHDISPLAY_EXPLODE 0x4
|
||||
#define MESHDISPLAY_MESHLET 0x5
|
||||
|
||||
// extra values below
|
||||
#define MESHDISPLAY_SECONDARY_ALPHA 0x5
|
||||
#define MESHDISPLAY_SECONDARY_ALPHA 0x6
|
||||
|
||||
#define MAX_NUM_MESHLETS (512 * 1024)
|
||||
|
||||
|
||||
@@ -37,6 +37,70 @@ struct meshA2V
|
||||
float4 secondary : sec;
|
||||
};
|
||||
|
||||
// This function is mostly duplicated between 'mesh.hlsl' and 'mesh.vert'.
|
||||
// Without a convenient shared common source, changes to one should be
|
||||
// reflected in the other.
|
||||
void vtxExploder(in uint vtxID, inout float3 pos, inout float3 secondary)
|
||||
{
|
||||
if(exploderScale > 0.0f)
|
||||
{
|
||||
float nonLinearVtxExplodeScale =
|
||||
4.0f * exploderScale * vtxExploderSNorm * vtxExploderSNorm * vtxExploderSNorm;
|
||||
|
||||
// A vertex might be coincident with our 'exploderCentre' so that, when normalized,
|
||||
// can give us INFs/NaNs that, even if multiplied by a zero 'exploderScale', can
|
||||
// leave us with bad numbers (as seems to be the case with glsl/vulkan, but not hlsl).
|
||||
// Still, we should make this case safe for when we have a non-zero 'exploderScale' -
|
||||
float3 offset = pos - exploderCentre;
|
||||
float offsetDistSquared = dot(offset, offset);
|
||||
float3 safeExplodeDir = offset * rsqrt(max(offsetDistSquared, FLT_EPSILON));
|
||||
|
||||
float displacement =
|
||||
nonLinearVtxExplodeScale * ((float((vtxID >> 1u) & 0xfu) / 15.0f) * 1.5f - 0.5f);
|
||||
pos += (safeExplodeDir * displacement);
|
||||
|
||||
// For the exploder visualisation, colour verts based on vertex ID, which we
|
||||
// store in secondary.
|
||||
//
|
||||
// Interpolate a colour gradient from 0.0 to 1.0 and back to 0.0 for vertex IDs
|
||||
// 0 to 16 to 32 respectively -
|
||||
// 1 - | .`.
|
||||
// | .` `.
|
||||
// | .` | `.
|
||||
// 0.5-| .` `.
|
||||
// | .` | `. .
|
||||
// |.` `. .`
|
||||
// 0.0-+-----------+-----------+--- vtx IDs
|
||||
// 0 16 32
|
||||
|
||||
float vtxIDMod32Div16 = (float)(vtxID % 32u) / 16.0f; // 0: 0.0 16: 1.0 31: 1.94
|
||||
float descending = floor(vtxIDMod32Div16); // 0..15: 0.0 16..31: 1.0
|
||||
float gradientVal = abs(vtxIDMod32Div16 - (2.0f * descending)); // 0.0..1.0
|
||||
|
||||
// Use a hopefully fairly intuitive temperature gradient scheme to help visualise
|
||||
// contiguous/nearby sequences of vertices, which should also show up breaks in
|
||||
// colour where verts aren't shared between adjacent primitives.
|
||||
const float3 gradientColours[5] = {
|
||||
float3(0.004f, 0.002f, 0.025f), // 0.0..0.25: Dark blue
|
||||
float3(0.305f, 0.001f, 0.337f), // 0.25..0.5: Purple
|
||||
float3(0.665f, 0.033f, 0.133f), // 0.5..0.75: Purple orange
|
||||
float3(1.000f, 0.468f, 0.000f), // 0.75..1.0: Orange
|
||||
float3(1.000f, 1.000f, 1.000f) // 1.0: White
|
||||
};
|
||||
|
||||
uint gradientSectionStartIdx = (uint)(gradientVal * 4.0f);
|
||||
uint gradientSectionEndIdx = min(gradientSectionStartIdx + 1u, 4u);
|
||||
float3 gradSectionStartCol = gradientColours[gradientSectionStartIdx];
|
||||
float3 gradSectionEndCol = gradientColours[gradientSectionEndIdx];
|
||||
|
||||
float sectionLerp = gradientVal - (float)gradientSectionStartIdx * 0.25f;
|
||||
float3 gradCol = lerp(gradientColours[gradientSectionStartIdx],
|
||||
gradientColours[gradientSectionEndIdx], sectionLerp);
|
||||
|
||||
secondary = gradCol;
|
||||
}
|
||||
}
|
||||
|
||||
StructuredBuffer<uint4> meshletSizesBuf : register(t0);
|
||||
|
||||
float4 unpackUnorm4x8(uint value)
|
||||
@@ -118,6 +182,7 @@ meshV2F RENDERDOC_MeshVS(meshA2V IN, uint vid : SV_VertexID)
|
||||
float2(1.0f, 1.0f)};
|
||||
|
||||
float4 pos = IN.pos;
|
||||
vtxExploder(vid, pos.xyz, IN.secondary.xyz);
|
||||
|
||||
if(homogenousInput == 0u)
|
||||
{
|
||||
@@ -214,6 +279,12 @@ float4 RENDERDOC_MeshPS(meshV2F IN)
|
||||
|
||||
return float4(MeshColour.xyz * abs(dot(lightDir, IN.norm)), 1);
|
||||
}
|
||||
else if(type == MESHDISPLAY_EXPLODE)
|
||||
{
|
||||
float3 lightDir = normalize(float3(0, -0.3f, -1));
|
||||
|
||||
return float4(IN.secondary.xyz * abs(dot(lightDir, IN.norm)), 1);
|
||||
}
|
||||
else // if(type == MESHDISPLAY_SOLID)
|
||||
return float4(MeshColour.xyz, 1);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,19 @@
|
||||
|
||||
#include "data/hlsl/hlsl_cbuffers.h"
|
||||
|
||||
static uint32_t VisModeToMeshDisplayFormat(const MeshDisplay &cfg)
|
||||
{
|
||||
switch(cfg.visualisationMode)
|
||||
{
|
||||
default: return (uint32_t)cfg.visualisationMode;
|
||||
case Visualisation::Secondary:
|
||||
return cfg.second.showAlpha ? MESHDISPLAY_SECONDARY_ALPHA : MESHDISPLAY_SECONDARY;
|
||||
case Visualisation::Meshlet:
|
||||
RDCERR("D3D11 does not support meshlet rendering");
|
||||
return MESHDISPLAY_SOLID;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondaryDraws,
|
||||
const MeshDisplay &cfg)
|
||||
{
|
||||
@@ -58,6 +71,12 @@ void D3D11Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
||||
vertexData.SpriteSize = Vec2f();
|
||||
vertexData.homogenousInput = cfg.position.unproject;
|
||||
vertexData.vtxExploderSNorm = cfg.vtxExploderSliderSNorm;
|
||||
vertexData.exploderCentre =
|
||||
Vec3f((cfg.minBounds.x + cfg.maxBounds.x) * 0.5f, (cfg.minBounds.y + cfg.maxBounds.y) * 0.5f,
|
||||
(cfg.minBounds.z + cfg.maxBounds.z) * 0.5f);
|
||||
vertexData.exploderScale =
|
||||
(cfg.visualisationMode == Visualisation::Explode) ? cfg.exploderScale : 0.0f;
|
||||
|
||||
Vec4f col(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
ID3D11Buffer *psCBuf = GetDebugManager()->MakeCBuffer(&col, sizeof(col));
|
||||
@@ -260,27 +279,21 @@ void D3D11Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
m_pImmediateContext->IASetIndexBuffer(NULL, DXGI_FORMAT_UNKNOWN, NULL);
|
||||
|
||||
// draw solid shaded mode
|
||||
if(cfg.solidShadeMode != SolidShade::NoSolid && cfg.position.topology < Topology::PatchList_1CPs)
|
||||
if(cfg.visualisationMode != Visualisation::NoSolid &&
|
||||
cfg.position.topology < Topology::PatchList_1CPs)
|
||||
{
|
||||
m_pImmediateContext->RSSetState(m_General.RasterState);
|
||||
|
||||
m_pImmediateContext->IASetPrimitiveTopology(topo);
|
||||
|
||||
pixelData.MeshDisplayFormat = (int)cfg.solidShadeMode;
|
||||
if(cfg.solidShadeMode == SolidShade::Meshlet)
|
||||
{
|
||||
RDCERR("D3D11 does not support mesh rendering");
|
||||
pixelData.MeshDisplayFormat = (int)SolidShade::Solid;
|
||||
}
|
||||
|
||||
if(cfg.solidShadeMode == SolidShade::Secondary && cfg.second.showAlpha)
|
||||
pixelData.MeshDisplayFormat = MESHDISPLAY_SECONDARY_ALPHA;
|
||||
pixelData.MeshDisplayFormat = VisModeToMeshDisplayFormat(cfg);
|
||||
|
||||
pixelData.MeshColour = Vec3f(0.8f, 0.8f, 0.0f);
|
||||
GetDebugManager()->FillCBuffer(psCBuf, &pixelData, sizeof(pixelData));
|
||||
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
||||
|
||||
if(cfg.solidShadeMode == SolidShade::Lit)
|
||||
if(cfg.visualisationMode == Visualisation::Lit ||
|
||||
cfg.visualisationMode == Visualisation::Explode)
|
||||
{
|
||||
MeshGeometryCBuffer geomData;
|
||||
|
||||
@@ -298,12 +311,13 @@ void D3D11Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
else
|
||||
m_pImmediateContext->Draw(cfg.position.numIndices, 0);
|
||||
|
||||
if(cfg.solidShadeMode == SolidShade::Lit)
|
||||
if(cfg.visualisationMode == Visualisation::Lit ||
|
||||
cfg.visualisationMode == Visualisation::Explode)
|
||||
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
|
||||
}
|
||||
|
||||
// draw wireframe mode
|
||||
if(cfg.solidShadeMode == SolidShade::NoSolid || cfg.wireframeDraw ||
|
||||
if(cfg.visualisationMode == Visualisation::NoSolid || cfg.wireframeDraw ||
|
||||
cfg.position.topology >= Topology::PatchList_1CPs)
|
||||
{
|
||||
m_pImmediateContext->RSSetState(m_MeshRender.WireframeRasterState);
|
||||
@@ -335,6 +349,8 @@ void D3D11Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
// set up state for drawing helpers
|
||||
{
|
||||
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
||||
vertexData.vtxExploderSNorm = 0.0f;
|
||||
vertexData.exploderScale = 0.0f;
|
||||
GetDebugManager()->FillCBuffer(vsCBuf, &vertexData, sizeof(vertexData));
|
||||
|
||||
m_pImmediateContext->RSSetState(m_MeshRender.SolidRasterState);
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
|
||||
RDOC_EXTERN_CONFIG(bool, D3D12_Debug_SingleSubmitFlushing);
|
||||
|
||||
static uint32_t VisModeToMeshDisplayFormat(const MeshDisplay &cfg)
|
||||
{
|
||||
switch(cfg.visualisationMode)
|
||||
{
|
||||
default: return (uint32_t)cfg.visualisationMode;
|
||||
case Visualisation::Secondary:
|
||||
return cfg.second.showAlpha ? MESHDISPLAY_SECONDARY_ALPHA : MESHDISPLAY_SECONDARY;
|
||||
}
|
||||
}
|
||||
|
||||
MeshDisplayPipelines D3D12DebugManager::CacheMeshDisplayPipelines(const MeshFormat &primary,
|
||||
const MeshFormat &secondary)
|
||||
{
|
||||
@@ -93,7 +103,7 @@ MeshDisplayPipelines D3D12DebugManager::CacheMeshDisplayPipelines(const MeshForm
|
||||
|
||||
MeshDisplayPipelines &cache = m_CachedMeshPipelines[key];
|
||||
|
||||
if(cache.pipes[(uint32_t)SolidShade::NoSolid] != NULL)
|
||||
if(cache.pipes[(uint32_t)Visualisation::NoSolid] != NULL)
|
||||
return cache;
|
||||
|
||||
cache.rootsig = m_MeshRootSig;
|
||||
@@ -276,6 +286,12 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
||||
vertexData.SpriteSize = Vec2f();
|
||||
vertexData.homogenousInput = cfg.position.unproject;
|
||||
vertexData.vtxExploderSNorm = cfg.vtxExploderSliderSNorm;
|
||||
vertexData.exploderCentre =
|
||||
Vec3f((cfg.minBounds.x + cfg.maxBounds.x) * 0.5f, (cfg.minBounds.y + cfg.maxBounds.y) * 0.5f,
|
||||
(cfg.minBounds.z + cfg.maxBounds.z) * 0.5f);
|
||||
vertexData.exploderScale =
|
||||
(cfg.visualisationMode == Visualisation::Explode) ? cfg.exploderScale : 0.0f;
|
||||
vertexData.vertMeshDisplayFormat = MESHDISPLAY_SOLID;
|
||||
|
||||
MeshPixelCBuffer pixelData;
|
||||
@@ -425,13 +441,13 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
}
|
||||
|
||||
SolidShade solidShadeMode = cfg.solidShadeMode;
|
||||
|
||||
// can't support secondary shading without a buffer - no pipeline will have been created
|
||||
if(solidShadeMode == SolidShade::Secondary && cfg.second.vertexResourceId == ResourceId())
|
||||
solidShadeMode = SolidShade::NoSolid;
|
||||
const Visualisation finalVisualisation = (cfg.visualisationMode == Visualisation::Secondary &&
|
||||
cfg.second.vertexResourceId == ResourceId())
|
||||
? Visualisation::NoSolid
|
||||
: cfg.visualisationMode;
|
||||
|
||||
if(solidShadeMode == SolidShade::Secondary)
|
||||
if(finalVisualisation == Visualisation::Secondary)
|
||||
{
|
||||
D3D12MarkerRegion::Set(list, "Secondary");
|
||||
|
||||
@@ -454,28 +470,32 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
}
|
||||
|
||||
// solid render
|
||||
if(solidShadeMode != SolidShade::NoSolid && cfg.position.topology < Topology::PatchList)
|
||||
if(finalVisualisation != Visualisation::NoSolid && cfg.position.topology < Topology::PatchList)
|
||||
{
|
||||
D3D12MarkerRegion region(list, "Solid render");
|
||||
|
||||
ID3D12PipelineState *pipe = NULL;
|
||||
switch(solidShadeMode)
|
||||
switch(finalVisualisation)
|
||||
{
|
||||
default:
|
||||
case SolidShade::Solid: pipe = cache.pipes[MeshDisplayPipelines::ePipe_SolidDepth]; break;
|
||||
case SolidShade::Lit:
|
||||
case Visualisation::Solid: pipe = cache.pipes[MeshDisplayPipelines::ePipe_SolidDepth]; break;
|
||||
case Visualisation::Lit:
|
||||
case Visualisation::Explode:
|
||||
pipe = cache.pipes[MeshDisplayPipelines::ePipe_Lit];
|
||||
// point list topologies don't have lighting obvious, just render them as solid
|
||||
if(!pipe)
|
||||
pipe = cache.pipes[MeshDisplayPipelines::ePipe_SolidDepth];
|
||||
break;
|
||||
case SolidShade::Secondary: pipe = cache.pipes[MeshDisplayPipelines::ePipe_Secondary]; break;
|
||||
case SolidShade::Meshlet: pipe = cache.pipes[MeshDisplayPipelines::ePipe_SolidDepth]; break;
|
||||
case Visualisation::Secondary:
|
||||
pipe = cache.pipes[MeshDisplayPipelines::ePipe_Secondary];
|
||||
break;
|
||||
case Visualisation::Meshlet:
|
||||
pipe = cache.pipes[MeshDisplayPipelines::ePipe_SolidDepth];
|
||||
break;
|
||||
}
|
||||
|
||||
pixelData.MeshDisplayFormat = (int)cfg.solidShadeMode;
|
||||
if(cfg.solidShadeMode == SolidShade::Secondary && cfg.second.showAlpha)
|
||||
pixelData.MeshDisplayFormat = MESHDISPLAY_SECONDARY_ALPHA;
|
||||
pixelData.MeshDisplayFormat = VisModeToMeshDisplayFormat(cfg);
|
||||
|
||||
pixelData.MeshColour = Vec3f(0.8f, 0.8f, 0.0f);
|
||||
|
||||
list->SetPipelineState(pipe);
|
||||
@@ -483,7 +503,7 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
|
||||
size_t numMeshlets = RDCMIN(cfg.position.meshletSizes.size(), (size_t)MAX_NUM_MESHLETS);
|
||||
|
||||
if(cfg.solidShadeMode == SolidShade::Meshlet)
|
||||
if(finalVisualisation == Visualisation::Meshlet)
|
||||
{
|
||||
vertexData.meshletCount = (uint32_t)numMeshlets;
|
||||
vertexData.meshletOffset = (uint32_t)cfg.position.meshletOffset;
|
||||
@@ -496,7 +516,7 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
|
||||
list->SetGraphicsRootConstantBufferView(0, vsCBSolid);
|
||||
|
||||
if(solidShadeMode == SolidShade::Lit)
|
||||
if(finalVisualisation == Visualisation::Lit || finalVisualisation == Visualisation::Explode)
|
||||
{
|
||||
MeshGeometryCBuffer geomData;
|
||||
geomData.InvProj = projMat.Inverse();
|
||||
@@ -540,7 +560,7 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
}
|
||||
|
||||
// wireframe render
|
||||
if(solidShadeMode == SolidShade::NoSolid || cfg.wireframeDraw ||
|
||||
if(finalVisualisation == Visualisation::NoSolid || cfg.wireframeDraw ||
|
||||
cfg.position.topology >= Topology::PatchList)
|
||||
{
|
||||
D3D12MarkerRegion region(list, "Wireframe render");
|
||||
@@ -603,6 +623,8 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secon
|
||||
pixelData.MeshDisplayFormat = MESHDISPLAY_SOLID;
|
||||
|
||||
vertexData.homogenousInput = 0U;
|
||||
vertexData.vtxExploderSNorm = 0.0f;
|
||||
vertexData.exploderScale = 0.0f;
|
||||
|
||||
vsCB = GetDebugManager()->UploadConstants(&vertexData, sizeof(vertexData));
|
||||
|
||||
|
||||
@@ -33,6 +33,16 @@
|
||||
#define OPENGL 1
|
||||
#include "data/glsl/glsl_ubos_cpp.h"
|
||||
|
||||
static int VisModeToMeshDisplayFormat(const MeshDisplay &cfg)
|
||||
{
|
||||
switch(cfg.visualisationMode)
|
||||
{
|
||||
default: return (int)cfg.visualisationMode;
|
||||
case Visualisation::Secondary:
|
||||
return cfg.second.showAlpha ? MESHDISPLAY_SECONDARY_ALPHA : MESHDISPLAY_SECONDARY;
|
||||
}
|
||||
}
|
||||
|
||||
void GLReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondaryDraws,
|
||||
const MeshDisplay &cfg)
|
||||
{
|
||||
@@ -113,6 +123,12 @@ void GLReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondar
|
||||
uboParams.mvp = ModelViewProj;
|
||||
uboParams.homogenousInput = cfg.position.unproject;
|
||||
uboParams.pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
uboParams.vtxExploderSNorm = cfg.vtxExploderSliderSNorm;
|
||||
uboParams.exploderScale =
|
||||
(cfg.visualisationMode == Visualisation::Explode) ? cfg.exploderScale : 0.0f;
|
||||
uboParams.exploderCentre =
|
||||
Vec3f((cfg.minBounds.x + cfg.maxBounds.x) * 0.5f, (cfg.minBounds.y + cfg.maxBounds.y) * 0.5f,
|
||||
(cfg.minBounds.z + cfg.maxBounds.z) * 0.5f);
|
||||
|
||||
if(!secondaryDraws.empty())
|
||||
{
|
||||
@@ -333,13 +349,15 @@ void GLReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondar
|
||||
drv.glEnable(eGL_DEPTH_TEST);
|
||||
|
||||
// solid render
|
||||
if(cfg.solidShadeMode != SolidShade::NoSolid && topo != eGL_PATCHES)
|
||||
if(cfg.visualisationMode != Visualisation::NoSolid && topo != eGL_PATCHES)
|
||||
{
|
||||
drv.glDepthFunc(eGL_LESS);
|
||||
|
||||
GLuint solidProg = prog;
|
||||
|
||||
if(cfg.solidShadeMode == SolidShade::Lit && DebugData.meshgsProg[0])
|
||||
if((cfg.visualisationMode == Visualisation::Lit ||
|
||||
cfg.visualisationMode == Visualisation::Explode) &&
|
||||
DebugData.meshgsProg[0])
|
||||
{
|
||||
// pick program with GS for per-face lighting
|
||||
solidProg = DebugData.meshgsProg[progidx];
|
||||
@@ -363,18 +381,11 @@ void GLReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondar
|
||||
return;
|
||||
}
|
||||
|
||||
soliddata->mvp = ModelViewProj;
|
||||
soliddata->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
soliddata->homogenousInput = cfg.position.unproject;
|
||||
uboParams.color = Vec4f(0.8f, 0.8f, 0.0f, 1.0f);
|
||||
uboParams.displayFormat = VisModeToMeshDisplayFormat(cfg);
|
||||
*soliddata = uboParams;
|
||||
|
||||
soliddata->color = Vec4f(0.8f, 0.8f, 0.0f, 1.0f);
|
||||
|
||||
uint32_t OutputDisplayFormat = (uint32_t)cfg.solidShadeMode;
|
||||
if(cfg.solidShadeMode == SolidShade::Secondary && cfg.second.showAlpha)
|
||||
OutputDisplayFormat = MESHDISPLAY_SECONDARY_ALPHA;
|
||||
soliddata->displayFormat = OutputDisplayFormat;
|
||||
|
||||
if(cfg.solidShadeMode == SolidShade::Lit)
|
||||
if(cfg.visualisationMode == Visualisation::Lit || cfg.visualisationMode == Visualisation::Explode)
|
||||
soliddata->invProj = projMat.Inverse();
|
||||
|
||||
drv.glUnmapBuffer(eGL_UNIFORM_BUFFER);
|
||||
@@ -417,14 +428,14 @@ void GLReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondar
|
||||
|
||||
drv.glDepthFunc(eGL_ALWAYS);
|
||||
|
||||
uboParams.displayFormat = MESHDISPLAY_SOLID;
|
||||
|
||||
// wireframe render
|
||||
if(cfg.solidShadeMode == SolidShade::NoSolid || cfg.wireframeDraw || topo == eGL_PATCHES)
|
||||
if(cfg.visualisationMode == Visualisation::NoSolid || cfg.wireframeDraw || topo == eGL_PATCHES)
|
||||
{
|
||||
uboParams.color = Vec4f(cfg.position.meshColor.x, cfg.position.meshColor.y,
|
||||
cfg.position.meshColor.z, cfg.position.meshColor.w);
|
||||
|
||||
uboParams.displayFormat = MESHDISPLAY_SOLID;
|
||||
|
||||
if(!IsGLES)
|
||||
drv.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE);
|
||||
|
||||
@@ -469,6 +480,10 @@ void GLReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondar
|
||||
// helpers always use basic float-input program
|
||||
drv.glUseProgram(DebugData.meshProg[0]);
|
||||
|
||||
uboParams.vtxExploderSNorm = 0.0f;
|
||||
uboParams.exploderScale = 0.0f;
|
||||
uboParams.exploderCentre = Vec3f();
|
||||
|
||||
if(cfg.showBBox)
|
||||
{
|
||||
Vec4f a = Vec4f(cfg.minBounds.x, cfg.minBounds.y, cfg.minBounds.z, cfg.minBounds.w);
|
||||
|
||||
@@ -2732,7 +2732,9 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
|
||||
data->displayFormat = 0;
|
||||
data->rawoutput = 1;
|
||||
data->flipY = 0;
|
||||
data->padding = Vec2f();
|
||||
data->vtxExploderSNorm = 0.0f;
|
||||
data->exploderScale = 0.0f;
|
||||
data->exploderCentre = Vec3f();
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
uint32_t viewOffs = 0;
|
||||
|
||||
@@ -37,6 +37,16 @@
|
||||
|
||||
RDOC_EXTERN_CONFIG(bool, Vulkan_Debug_SingleSubmitFlushing);
|
||||
|
||||
static int VisModeToMeshDisplayFormat(Visualisation vis, bool showAlpha)
|
||||
{
|
||||
switch(vis)
|
||||
{
|
||||
default: return (int)vis;
|
||||
case Visualisation::Secondary:
|
||||
return showAlpha ? MESHDISPLAY_SECONDARY_ALPHA : MESHDISPLAY_SECONDARY;
|
||||
}
|
||||
}
|
||||
|
||||
VKMeshDisplayPipelines VulkanDebugManager::CacheMeshDisplayPipelines(VkPipelineLayout pipeLayout,
|
||||
const MeshFormat &primary,
|
||||
const MeshFormat &secondary)
|
||||
@@ -138,7 +148,7 @@ VKMeshDisplayPipelines VulkanDebugManager::CacheMeshDisplayPipelines(VkPipelineL
|
||||
|
||||
VKMeshDisplayPipelines &cache = m_CachedMeshPipelines[key];
|
||||
|
||||
if(cache.pipes[(uint32_t)SolidShade::NoSolid] != VK_NULL_HANDLE)
|
||||
if(cache.pipes[(uint32_t)Visualisation::NoSolid] != VK_NULL_HANDLE)
|
||||
return cache;
|
||||
|
||||
const VkDevDispatchTable *vt = ObjDisp(m_Device);
|
||||
@@ -526,6 +536,25 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv));
|
||||
}
|
||||
|
||||
// can't support secondary shading without a buffer - no pipeline will have been created
|
||||
const Visualisation finalVisualisation = (cfg.visualisationMode == Visualisation::Secondary &&
|
||||
cfg.second.vertexResourceId == ResourceId())
|
||||
? Visualisation::NoSolid
|
||||
: cfg.visualisationMode;
|
||||
|
||||
MeshUBOData meshUniforms = {};
|
||||
meshUniforms.mvp = ModelViewProj;
|
||||
meshUniforms.displayFormat = MESHDISPLAY_SOLID;
|
||||
meshUniforms.homogenousInput = cfg.position.unproject;
|
||||
meshUniforms.pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
meshUniforms.rawoutput = 0;
|
||||
meshUniforms.vtxExploderSNorm = cfg.vtxExploderSliderSNorm;
|
||||
meshUniforms.exploderScale =
|
||||
(finalVisualisation == Visualisation::Explode) ? cfg.exploderScale : 0.0f;
|
||||
meshUniforms.exploderCentre =
|
||||
Vec3f((cfg.minBounds.x + cfg.maxBounds.x) * 0.5f, (cfg.minBounds.y + cfg.maxBounds.y) * 0.5f,
|
||||
(cfg.minBounds.z + cfg.maxBounds.z) * 0.5f);
|
||||
|
||||
uint32_t dynOffs[2] = {};
|
||||
|
||||
if(!secondaryDraws.empty())
|
||||
@@ -543,13 +572,10 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = Vec4f(fmt.meshColor.x, fmt.meshColor.y, fmt.meshColor.z, fmt.meshColor.w);
|
||||
data->homogenousInput = cfg.position.unproject;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->displayFormat = MESHDISPLAY_SOLID;
|
||||
data->rawoutput = 0;
|
||||
data->flipY = (cfg.position.flipY == fmt.flipY) ? 0 : 1;
|
||||
meshUniforms.color =
|
||||
Vec4f(fmt.meshColor.x, fmt.meshColor.y, fmt.meshColor.z, fmt.meshColor.w);
|
||||
meshUniforms.flipY = (cfg.position.flipY == fmt.flipY) ? 0 : 1;
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
@@ -663,13 +689,7 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
vt->CmdBindVertexBuffers(Unwrap(cmd), 0, 1, UnwrapPtr(vb), &offs);
|
||||
}
|
||||
|
||||
SolidShade solidShadeMode = cfg.solidShadeMode;
|
||||
|
||||
// can't support secondary shading without a buffer - no pipeline will have been created
|
||||
if(solidShadeMode == SolidShade::Secondary && cfg.second.vertexResourceId == ResourceId())
|
||||
solidShadeMode = SolidShade::NoSolid;
|
||||
|
||||
if(solidShadeMode == SolidShade::Secondary)
|
||||
if(finalVisualisation == Visualisation::Secondary)
|
||||
{
|
||||
VkBuffer vb =
|
||||
m_pDriver->GetResourceManager()->GetCurrentHandle<VkBuffer>(cfg.second.vertexResourceId);
|
||||
@@ -687,53 +707,49 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
}
|
||||
|
||||
// solid render
|
||||
if(solidShadeMode != SolidShade::NoSolid && cfg.position.topology < Topology::PatchList)
|
||||
if(finalVisualisation != Visualisation::NoSolid && cfg.position.topology < Topology::PatchList)
|
||||
{
|
||||
VkPipeline pipe = VK_NULL_HANDLE;
|
||||
switch(solidShadeMode)
|
||||
switch(finalVisualisation)
|
||||
{
|
||||
default:
|
||||
case SolidShade::Solid: pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_SolidDepth]; break;
|
||||
case SolidShade::Lit:
|
||||
case Visualisation::Solid:
|
||||
pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_SolidDepth];
|
||||
break;
|
||||
case Visualisation::Lit:
|
||||
case Visualisation::Explode:
|
||||
pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_Lit];
|
||||
// point list topologies don't have lighting obvious, just render them as solid
|
||||
// Also, can't support lit rendering without the pipeline - maybe geometry shader wasn't supported.
|
||||
if(pipe == VK_NULL_HANDLE)
|
||||
pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_SolidDepth];
|
||||
break;
|
||||
case SolidShade::Secondary:
|
||||
case Visualisation::Secondary:
|
||||
pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_Secondary];
|
||||
break;
|
||||
case SolidShade::Meshlet: pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_SolidDepth]; break;
|
||||
case Visualisation::Meshlet:
|
||||
pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_SolidDepth];
|
||||
break;
|
||||
}
|
||||
|
||||
// can't support lit rendering without the pipeline - maybe geometry shader wasn't supported.
|
||||
if(solidShadeMode == SolidShade::Lit && pipe == VK_NULL_HANDLE)
|
||||
pipe = cache.pipes[VKMeshDisplayPipelines::ePipe_SolidDepth];
|
||||
|
||||
MeshUBOData *data = (MeshUBOData *)m_MeshRender.UBO.Map(&dynOffs[0]);
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
if(solidShadeMode == SolidShade::Lit)
|
||||
data->invProj = projMat.Inverse();
|
||||
if(finalVisualisation == Visualisation::Lit || finalVisualisation == Visualisation::Explode)
|
||||
meshUniforms.invProj = projMat.Inverse();
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = Vec4f(0.8f, 0.8f, 0.0f, 1.0f);
|
||||
data->homogenousInput = cfg.position.unproject;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->displayFormat = (uint32_t)solidShadeMode;
|
||||
data->rawoutput = 0;
|
||||
meshUniforms.color = Vec4f(0.8f, 0.8f, 0.0f, 1.0f);
|
||||
meshUniforms.displayFormat = VisModeToMeshDisplayFormat(finalVisualisation, cfg.second.showAlpha);
|
||||
meshUniforms.flipY = 0;
|
||||
|
||||
if(solidShadeMode == SolidShade::Secondary && cfg.second.showAlpha)
|
||||
data->displayFormat = MESHDISPLAY_SECONDARY_ALPHA;
|
||||
|
||||
if(solidShadeMode == SolidShade::Meshlet)
|
||||
if(finalVisualisation == Visualisation::Meshlet)
|
||||
{
|
||||
size_t numMeshlets = RDCMIN(cfg.position.meshletSizes.size(), (size_t)MAX_NUM_MESHLETS);
|
||||
|
||||
uint32_t *meshletCounts = (uint32_t *)m_MeshRender.MeshletSSBO.Map(
|
||||
&dynOffs[1], AlignUp4(numMeshlets + 4) * sizeof(uint32_t));
|
||||
if(!data)
|
||||
if(!meshletCounts)
|
||||
return;
|
||||
|
||||
if(cfg.position.meshletSizes.size() > MAX_NUM_MESHLETS)
|
||||
@@ -751,13 +767,15 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
meshletCounts[i] = prefixCount;
|
||||
}
|
||||
|
||||
memcpy(&data->meshletColours[0].x, uniqueColors, sizeof(uniqueColors));
|
||||
RDCCOMPILE_ASSERT(sizeof(data->meshletColours) == sizeof(uniqueColors),
|
||||
memcpy(&meshUniforms.meshletColours[0].x, uniqueColors, sizeof(uniqueColors));
|
||||
RDCCOMPILE_ASSERT(sizeof(meshUniforms.meshletColours) == sizeof(uniqueColors),
|
||||
"Unique colors array is wrongly sized");
|
||||
|
||||
m_MeshRender.MeshletSSBO.Unmap();
|
||||
}
|
||||
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
@@ -789,8 +807,10 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
}
|
||||
}
|
||||
|
||||
meshUniforms.displayFormat = MESHDISPLAY_SOLID;
|
||||
|
||||
// wireframe render
|
||||
if(solidShadeMode == SolidShade::NoSolid || cfg.wireframeDraw ||
|
||||
if(finalVisualisation == Visualisation::NoSolid || cfg.wireframeDraw ||
|
||||
cfg.position.topology >= Topology::PatchList)
|
||||
{
|
||||
Vec4f wireCol =
|
||||
@@ -800,12 +820,8 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = wireCol;
|
||||
data->displayFormat = (uint32_t)SolidShade::Solid;
|
||||
data->homogenousInput = cfg.position.unproject;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->rawoutput = 0;
|
||||
meshUniforms.color = wireCol;
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
@@ -851,6 +867,11 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
|
||||
helper.vertexByteStride = sizeof(Vec4f);
|
||||
|
||||
meshUniforms.homogenousInput = 0;
|
||||
meshUniforms.vtxExploderSNorm = 0.0f;
|
||||
meshUniforms.exploderScale = 0.0f;
|
||||
meshUniforms.exploderCentre = Vec3f();
|
||||
|
||||
// cache pipelines for use in drawing wireframe helpers
|
||||
cache = GetDebugManager()->CacheMeshDisplayPipelines(m_MeshRender.PipeLayout, helper, helper);
|
||||
|
||||
@@ -893,12 +914,8 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = Vec4f(0.2f, 0.2f, 1.0f, 1.0f);
|
||||
data->displayFormat = (uint32_t)SolidShade::Solid;
|
||||
data->homogenousInput = 0;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->rawoutput = 0;
|
||||
meshUniforms.color = Vec4f(0.2f, 0.2f, 1.0f, 1.0f);
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
@@ -922,12 +939,8 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
data->displayFormat = (uint32_t)SolidShade::Solid;
|
||||
data->homogenousInput = 0;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->rawoutput = 0;
|
||||
meshUniforms.color = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
@@ -945,12 +958,8 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
data->displayFormat = (uint32_t)SolidShade::Solid;
|
||||
data->homogenousInput = 0;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->rawoutput = 0;
|
||||
meshUniforms.color = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
@@ -963,12 +972,8 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
data->displayFormat = (uint32_t)SolidShade::Solid;
|
||||
data->homogenousInput = 0;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->rawoutput = 0;
|
||||
meshUniforms.color = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
@@ -988,12 +993,8 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
data->mvp = ModelViewProj;
|
||||
data->color = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
data->displayFormat = (uint32_t)SolidShade::Solid;
|
||||
data->homogenousInput = 0;
|
||||
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
data->rawoutput = 0;
|
||||
meshUniforms.color = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
*data = meshUniforms;
|
||||
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
@@ -1088,17 +1089,14 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
else
|
||||
ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
||||
|
||||
MeshUBOData uniforms = {};
|
||||
uniforms.mvp = ModelViewProj;
|
||||
uniforms.color = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
uniforms.displayFormat = (uint32_t)SolidShade::Solid;
|
||||
uniforms.homogenousInput = cfg.position.unproject;
|
||||
uniforms.pointSpriteSize = Vec2f(0.0f, 0.0f);
|
||||
meshUniforms.mvp = ModelViewProj;
|
||||
meshUniforms.color = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
meshUniforms.homogenousInput = cfg.position.unproject;
|
||||
|
||||
MeshUBOData *ubodata = (MeshUBOData *)m_MeshRender.UBO.Map(&dynOffs[0]);
|
||||
if(!ubodata)
|
||||
return;
|
||||
*ubodata = uniforms;
|
||||
*ubodata = meshUniforms;
|
||||
m_MeshRender.UBO.Unmap();
|
||||
|
||||
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
@@ -1112,12 +1110,12 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
// render primitives
|
||||
|
||||
// Draw active primitive (red)
|
||||
uniforms.color = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
meshUniforms.color = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
// poke the color (this would be a good candidate for a push constant)
|
||||
ubodata = (MeshUBOData *)m_MeshRender.UBO.Map(&dynOffs[0]);
|
||||
if(!ubodata)
|
||||
return;
|
||||
*ubodata = uniforms;
|
||||
*ubodata = meshUniforms;
|
||||
m_MeshRender.UBO.Unmap();
|
||||
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
Unwrap(m_MeshRender.PipeLayout), 0, 1,
|
||||
@@ -1140,12 +1138,12 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
}
|
||||
|
||||
// Draw adjacent primitives (green)
|
||||
uniforms.color = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
meshUniforms.color = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
// poke the color (this would be a good candidate for a push constant)
|
||||
ubodata = (MeshUBOData *)m_MeshRender.UBO.Map(&dynOffs[0]);
|
||||
if(!ubodata)
|
||||
return;
|
||||
*ubodata = uniforms;
|
||||
*ubodata = meshUniforms;
|
||||
m_MeshRender.UBO.Unmap();
|
||||
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
Unwrap(m_MeshRender.PipeLayout), 0, 1,
|
||||
@@ -1173,15 +1171,15 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
float scale = 800.0f / float(m_DebugHeight);
|
||||
float asp = float(m_DebugWidth) / float(m_DebugHeight);
|
||||
|
||||
uniforms.pointSpriteSize = Vec2f(scale / asp, scale);
|
||||
meshUniforms.pointSpriteSize = Vec2f(scale / asp, scale);
|
||||
|
||||
// Draw active vertex (blue)
|
||||
uniforms.color = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
meshUniforms.color = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
// poke the color (this would be a good candidate for a push constant)
|
||||
ubodata = (MeshUBOData *)m_MeshRender.UBO.Map(&dynOffs[0]);
|
||||
if(!ubodata)
|
||||
return;
|
||||
*ubodata = uniforms;
|
||||
*ubodata = meshUniforms;
|
||||
m_MeshRender.UBO.Unmap();
|
||||
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
Unwrap(m_MeshRender.PipeLayout), 0, 1,
|
||||
@@ -1221,12 +1219,12 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &seco
|
||||
}
|
||||
|
||||
// Draw inactive vertices (green)
|
||||
uniforms.color = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
meshUniforms.color = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
// poke the color (this would be a good candidate for a push constant)
|
||||
ubodata = (MeshUBOData *)m_MeshRender.UBO.Map(&dynOffs[0]);
|
||||
if(!ubodata)
|
||||
return;
|
||||
*ubodata = uniforms;
|
||||
*ubodata = meshUniforms;
|
||||
m_MeshRender.UBO.Unmap();
|
||||
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
Unwrap(m_MeshRender.PipeLayout), 0, 1,
|
||||
|
||||
@@ -118,7 +118,7 @@ class Mesh_Zoo():
|
||||
|
||||
rdtest.log.success("Base rendering is as expected")
|
||||
|
||||
self.cfg.solidShadeMode = rd.SolidShade.Secondary
|
||||
self.cfg.visualisationMode = rd.Visualisation.Secondary
|
||||
self.cfg.wireframeDraw = False
|
||||
|
||||
# allow for blending with white for the frustum
|
||||
@@ -244,7 +244,7 @@ class Mesh_Zoo():
|
||||
|
||||
rdtest.log.success("Rendering of float2 color secondary in instance 1 is as expected")
|
||||
|
||||
self.cfg.solidShadeMode = rd.SolidShade.NoSolid
|
||||
self.cfg.visualisationMode = rd.Visualisation.NoSolid
|
||||
self.cfg.showAllInstances = True
|
||||
|
||||
self.cache_output()
|
||||
@@ -370,10 +370,10 @@ class Mesh_Zoo():
|
||||
rdtest.log.success("Point picking is as expected")
|
||||
|
||||
self.cfg.highlightVert = rd.MeshDisplay.NoHighlight
|
||||
self.cfg.solidShadeMode = rd.SolidShade.Solid
|
||||
self.cfg.visualisationMode = rd.Visualisation.Solid
|
||||
|
||||
self.cache_output()
|
||||
self.cfg.solidShadeMode = rd.SolidShade.Lit
|
||||
self.cfg.visualisationMode = rd.Visualisation.Lit
|
||||
self.cache_output()
|
||||
|
||||
rdtest.log.success("Point solid and lit rendering works as expected")
|
||||
@@ -381,7 +381,7 @@ class Mesh_Zoo():
|
||||
self.controller.SetFrameEvent(self.find_action("Lines").next.eventId, False)
|
||||
|
||||
self.cache_output()
|
||||
self.cfg.solidShadeMode = rd.SolidShade.Lit
|
||||
self.cfg.visualisationMode = rd.Visualisation.Lit
|
||||
self.cache_output()
|
||||
|
||||
rdtest.log.success("Lines solid and lit rendering works as expected")
|
||||
|
||||
Reference in New Issue
Block a user