sg: Fix culling in layers
Pick-to: 6.10 6.9 6.8 Fixes: QTBUG-136611 Change-Id: If2a0a0365ca24360d850ffce98c0bec4a3961976 Reviewed-by: Jonas Karlsson <jonas.karlsson@qt.io>
This commit is contained in:
parent
8effdd97d9
commit
e32d335c8f
|
@ -130,10 +130,13 @@ void CustomRenderNode::prepare()
|
||||||
if (!m_pipeline) {
|
if (!m_pipeline) {
|
||||||
m_pipeline.reset(rhi->newGraphicsPipeline());
|
m_pipeline.reset(rhi->newGraphicsPipeline());
|
||||||
|
|
||||||
// If layer.enabled == true on our QQuickItem, the rendering face is flipped for
|
// If layer.enabled == true on our QQuickItem and layer.textureMirroring is the
|
||||||
// backends with isYUpInFrameBuffer == true (OpenGL). This does not happen with
|
// default MirrorVertically, the winding order needs to be inverted when
|
||||||
// RHI backends with isYUpInFrameBuffer == false. We swap the triangle winding
|
// isYUpInFrameBuffer == true (OpenGL). This does not happen with other backends,
|
||||||
// order to work around this.
|
// unless textureMirroring is changed so that the situation is inverted, meaning
|
||||||
|
// GL needs no adjustments while others need the opposite winding order. Here we
|
||||||
|
// choose the replicate, to a degree, what the scenegraph renderer does, but note that
|
||||||
|
// this is only correct as long as textureMirroring is not changed from the default.
|
||||||
m_pipeline->setFrontFace(renderTarget()->resourceType() == QRhiResource::TextureRenderTarget
|
m_pipeline->setFrontFace(renderTarget()->resourceType() == QRhiResource::TextureRenderTarget
|
||||||
&& rhi->isYUpInFramebuffer()
|
&& rhi->isYUpInFramebuffer()
|
||||||
? QRhiGraphicsPipeline::CW
|
? QRhiGraphicsPipeline::CW
|
||||||
|
|
|
@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE
|
||||||
QSGAbstractRendererPrivate::QSGAbstractRendererPrivate()
|
QSGAbstractRendererPrivate::QSGAbstractRendererPrivate()
|
||||||
: m_root_node(nullptr)
|
: m_root_node(nullptr)
|
||||||
, m_clear_color(Qt::transparent)
|
, m_clear_color(Qt::transparent)
|
||||||
|
, m_invertFrontFace(false)
|
||||||
{
|
{
|
||||||
m_projection_matrix.resize(1);
|
m_projection_matrix.resize(1);
|
||||||
m_projection_matrix_native_ndc.resize(1);
|
m_projection_matrix_native_ndc.resize(1);
|
||||||
|
@ -302,6 +303,24 @@ QMatrix4x4 QSGAbstractRenderer::projectionMatrixWithNativeNDC(int index) const
|
||||||
return d->m_projection_matrix_native_ndc[index];
|
return d->m_projection_matrix_native_ndc[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
void QSGAbstractRenderer::setInvertFrontFace(bool invert)
|
||||||
|
{
|
||||||
|
Q_D(QSGAbstractRenderer);
|
||||||
|
d->m_invertFrontFace = invert;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QSGAbstractRenderer::invertFrontFace() const
|
||||||
|
{
|
||||||
|
Q_D(const QSGAbstractRenderer);
|
||||||
|
return d->m_invertFrontFace;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the \a color to clear the framebuffer.
|
Sets the \a color to clear the framebuffer.
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ public:
|
||||||
QMatrix4x4 projectionMatrixWithNativeNDC(int index) const;
|
QMatrix4x4 projectionMatrixWithNativeNDC(int index) const;
|
||||||
int projectionMatrixCount() const;
|
int projectionMatrixCount() const;
|
||||||
int projectionMatrixWithNativeNDCCount() const;
|
int projectionMatrixWithNativeNDCCount() const;
|
||||||
|
void setInvertFrontFace(bool invert);
|
||||||
|
bool invertFrontFace() const;
|
||||||
|
|
||||||
void setClearColor(const QColor &color);
|
void setClearColor(const QColor &color);
|
||||||
QColor clearColor() const;
|
QColor clearColor() const;
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
|
|
||||||
QVarLengthArray<QMatrix4x4, 1> m_projection_matrix;
|
QVarLengthArray<QMatrix4x4, 1> m_projection_matrix;
|
||||||
QVarLengthArray<QMatrix4x4, 1> m_projection_matrix_native_ndc;
|
QVarLengthArray<QMatrix4x4, 1> m_projection_matrix_native_ndc;
|
||||||
uint m_mirrored : 1;
|
uint m_invertFrontFace : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
|
@ -2756,6 +2756,7 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms,
|
||||||
ps->setFlags(flags);
|
ps->setFlags(flags);
|
||||||
ps->setTopology(qsg_topology(m_gstate.drawMode, m_rhi));
|
ps->setTopology(qsg_topology(m_gstate.drawMode, m_rhi));
|
||||||
ps->setCullMode(m_gstate.cullMode);
|
ps->setCullMode(m_gstate.cullMode);
|
||||||
|
ps->setFrontFace(invertFrontFace() ? QRhiGraphicsPipeline::CW : QRhiGraphicsPipeline::CCW);
|
||||||
ps->setPolygonMode(m_gstate.polygonMode);
|
ps->setPolygonMode(m_gstate.polygonMode);
|
||||||
ps->setMultiViewCount(m_gstate.multiViewCount);
|
ps->setMultiViewCount(m_gstate.multiViewCount);
|
||||||
|
|
||||||
|
|
|
@ -410,22 +410,41 @@ void QSGRhiLayer::grab()
|
||||||
m_renderer->setDevicePixelRatio(m_dpr);
|
m_renderer->setDevicePixelRatio(m_dpr);
|
||||||
m_renderer->setDeviceRect(m_pixelSize);
|
m_renderer->setDeviceRect(m_pixelSize);
|
||||||
m_renderer->setViewportRect(m_pixelSize);
|
m_renderer->setViewportRect(m_pixelSize);
|
||||||
|
|
||||||
QRectF mirrored; // in logical coordinates (no dpr) since this gets passed to setProjectionMatrixToRect()
|
QRectF mirrored; // in logical coordinates (no dpr) since this gets passed to setProjectionMatrixToRect()
|
||||||
if (m_rhi->isYUpInFramebuffer()) {
|
|
||||||
|
// In the unlikely event of back/front face culling used by a custom
|
||||||
|
// material or effect in the layer, the default front face setting may be
|
||||||
|
// wrong. Rather, it needs to invert based on what the vertex shader does,
|
||||||
|
// and so on the rect (and so matrix) generated here.
|
||||||
|
bool frontFaceSwap = false;
|
||||||
|
|
||||||
|
if (m_rhi->isYUpInFramebuffer()) { // basically OpenGL
|
||||||
mirrored = QRectF(m_mirrorHorizontal ? m_logicalRect.right() : m_logicalRect.left(),
|
mirrored = QRectF(m_mirrorHorizontal ? m_logicalRect.right() : m_logicalRect.left(),
|
||||||
m_mirrorVertical ? m_logicalRect.bottom() : m_logicalRect.top(),
|
m_mirrorVertical ? m_logicalRect.bottom() : m_logicalRect.top(),
|
||||||
m_mirrorHorizontal ? -m_logicalRect.width() : m_logicalRect.width(),
|
m_mirrorHorizontal ? -m_logicalRect.width() : m_logicalRect.width(),
|
||||||
m_mirrorVertical ? -m_logicalRect.height() : m_logicalRect.height());
|
m_mirrorVertical ? -m_logicalRect.height() : m_logicalRect.height());
|
||||||
} else {
|
if (m_mirrorHorizontal)
|
||||||
|
frontFaceSwap = !frontFaceSwap;
|
||||||
|
if (m_mirrorVertical)
|
||||||
|
frontFaceSwap = !frontFaceSwap;
|
||||||
|
} else { // APIs other than OpenGL
|
||||||
mirrored = QRectF(m_mirrorHorizontal ? m_logicalRect.right() : m_logicalRect.left(),
|
mirrored = QRectF(m_mirrorHorizontal ? m_logicalRect.right() : m_logicalRect.left(),
|
||||||
m_mirrorVertical ? m_logicalRect.top() : m_logicalRect.bottom(),
|
m_mirrorVertical ? m_logicalRect.top() : m_logicalRect.bottom(),
|
||||||
m_mirrorHorizontal ? -m_logicalRect.width() : m_logicalRect.width(),
|
m_mirrorHorizontal ? -m_logicalRect.width() : m_logicalRect.width(),
|
||||||
m_mirrorVertical ? m_logicalRect.height() : -m_logicalRect.height());
|
m_mirrorVertical ? m_logicalRect.height() : -m_logicalRect.height());
|
||||||
|
if (m_mirrorHorizontal)
|
||||||
|
frontFaceSwap = !frontFaceSwap;
|
||||||
|
if (!m_mirrorVertical)
|
||||||
|
frontFaceSwap = !frontFaceSwap;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGAbstractRenderer::MatrixTransformFlags matrixFlags;
|
QSGAbstractRenderer::MatrixTransformFlags matrixFlags;
|
||||||
if (!m_rhi->isYUpInNDC())
|
if (!m_rhi->isYUpInNDC())
|
||||||
matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY;
|
matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY;
|
||||||
|
|
||||||
m_renderer->setProjectionMatrixToRect(mirrored, matrixFlags);
|
m_renderer->setProjectionMatrixToRect(mirrored, matrixFlags);
|
||||||
|
m_renderer->setInvertFrontFace(frontFaceSwap);
|
||||||
m_renderer->setClearColor(Qt::transparent);
|
m_renderer->setClearColor(Qt::transparent);
|
||||||
m_renderer->setRenderTarget({ m_rt, m_rtRp, m_context->currentFrameCommandBuffer() });
|
m_renderer->setRenderTarget({ m_rt, m_rtRp, m_context->currentFrameCommandBuffer() });
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: topLevel
|
||||||
|
width: 320
|
||||||
|
height: 480
|
||||||
|
|
||||||
|
// Make it a layer. Important because the winding order inverts based on the transforms the vertex shader does.
|
||||||
|
// The output should match culling_1 regardless.
|
||||||
|
layer.enabled: true
|
||||||
|
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: front
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "cornflowerblue"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Front"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: back
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "firebrick"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Back"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
Repeater {
|
||||||
|
model: ListModel {
|
||||||
|
ListElement {
|
||||||
|
foo: "No culling"
|
||||||
|
bar: ShaderEffect.NoCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Back-face culling"
|
||||||
|
bar: ShaderEffect.BackFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Front-face culling"
|
||||||
|
bar: ShaderEffect.FrontFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item{
|
||||||
|
id: item_0000
|
||||||
|
width: 320
|
||||||
|
height: 120
|
||||||
|
ShaderEffect {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: 10
|
||||||
|
width: 200
|
||||||
|
height: 100
|
||||||
|
cullMode: model.bar
|
||||||
|
property variant frontSource: front
|
||||||
|
property variant backSource: back
|
||||||
|
fragmentShader: "qrc:shaders/culling.frag.qsb"
|
||||||
|
transform: Rotation {
|
||||||
|
origin.x: 200
|
||||||
|
origin.y: 180 - 120 * index
|
||||||
|
axis { x: 0; y: 1; z: 0 }
|
||||||
|
angle: (turned == true) ? 180 : 0
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
font.pointSize: 10
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: 5
|
||||||
|
text: foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: topLevel
|
||||||
|
width: 320
|
||||||
|
height: 480
|
||||||
|
|
||||||
|
// Make it a layer. Important because the winding order inverts based on the transforms the vertex shader does.
|
||||||
|
// The output should match culling_1 regardless.
|
||||||
|
layer.enabled: true
|
||||||
|
|
||||||
|
// layer.textureMirroring by default is MirrorVertically. It has no effect
|
||||||
|
// on the visual result in this example, but it has a huge effect on the
|
||||||
|
// transformations internally. Change it to something to see the output is
|
||||||
|
// still the same.
|
||||||
|
layer.textureMirroring: ShaderEffectSource.MirrorHorizontally | ShaderEffectSource.MirrorVertically
|
||||||
|
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: front
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "cornflowerblue"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Front"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: back
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "firebrick"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Back"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
Repeater {
|
||||||
|
model: ListModel {
|
||||||
|
ListElement {
|
||||||
|
foo: "No culling"
|
||||||
|
bar: ShaderEffect.NoCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Back-face culling"
|
||||||
|
bar: ShaderEffect.BackFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Front-face culling"
|
||||||
|
bar: ShaderEffect.FrontFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item{
|
||||||
|
id: item_0000
|
||||||
|
width: 320
|
||||||
|
height: 120
|
||||||
|
ShaderEffect {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: 10
|
||||||
|
width: 200
|
||||||
|
height: 100
|
||||||
|
cullMode: model.bar
|
||||||
|
property variant frontSource: front
|
||||||
|
property variant backSource: back
|
||||||
|
fragmentShader: "qrc:shaders/culling.frag.qsb"
|
||||||
|
transform: Rotation {
|
||||||
|
origin.x: 200
|
||||||
|
origin.y: 180 - 120 * index
|
||||||
|
axis { x: 0; y: 1; z: 0 }
|
||||||
|
angle: (turned == true) ? 180 : 0
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
font.pointSize: 10
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: 5
|
||||||
|
text: foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: topLevel
|
||||||
|
width: 320
|
||||||
|
height: 480
|
||||||
|
|
||||||
|
// Make it a layer. Important because the winding order inverts based on the transforms the vertex shader does.
|
||||||
|
// The output should match culling_1 regardless.
|
||||||
|
layer.enabled: true
|
||||||
|
|
||||||
|
// layer.textureMirroring by default is MirrorVertically. It has no effect
|
||||||
|
// on the visual result in this example, but it has a huge effect on the
|
||||||
|
// transformations internally. Change it to something to see the output is
|
||||||
|
// still the same.
|
||||||
|
layer.textureMirroring: ShaderEffectSource.MirrorHorizontally
|
||||||
|
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: front
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "cornflowerblue"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Front"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: back
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "firebrick"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Back"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
Repeater {
|
||||||
|
model: ListModel {
|
||||||
|
ListElement {
|
||||||
|
foo: "No culling"
|
||||||
|
bar: ShaderEffect.NoCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Back-face culling"
|
||||||
|
bar: ShaderEffect.BackFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Front-face culling"
|
||||||
|
bar: ShaderEffect.FrontFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item{
|
||||||
|
id: item_0000
|
||||||
|
width: 320
|
||||||
|
height: 120
|
||||||
|
ShaderEffect {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: 10
|
||||||
|
width: 200
|
||||||
|
height: 100
|
||||||
|
cullMode: model.bar
|
||||||
|
property variant frontSource: front
|
||||||
|
property variant backSource: back
|
||||||
|
fragmentShader: "qrc:shaders/culling.frag.qsb"
|
||||||
|
transform: Rotation {
|
||||||
|
origin.x: 200
|
||||||
|
origin.y: 180 - 120 * index
|
||||||
|
axis { x: 0; y: 1; z: 0 }
|
||||||
|
angle: (turned == true) ? 180 : 0
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
font.pointSize: 10
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: 5
|
||||||
|
text: foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: topLevel
|
||||||
|
width: 320
|
||||||
|
height: 480
|
||||||
|
|
||||||
|
// Make it a layer. Important because the winding order inverts based on the transforms the vertex shader does.
|
||||||
|
// The output should match culling_1 regardless.
|
||||||
|
layer.enabled: true
|
||||||
|
|
||||||
|
// layer.textureMirroring by default is MirrorVertically. It has no effect
|
||||||
|
// on the visual result in this example, but it has a huge effect on the
|
||||||
|
// transformations internally. Change it to something to see the output is
|
||||||
|
// still the same.
|
||||||
|
layer.textureMirroring: ShaderEffectSource.NoMirroring
|
||||||
|
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: front
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "cornflowerblue"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Front"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: back
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "firebrick"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Back"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
Repeater {
|
||||||
|
model: ListModel {
|
||||||
|
ListElement {
|
||||||
|
foo: "No culling"
|
||||||
|
bar: ShaderEffect.NoCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Back-face culling"
|
||||||
|
bar: ShaderEffect.BackFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Front-face culling"
|
||||||
|
bar: ShaderEffect.FrontFaceCulling
|
||||||
|
turned: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item{
|
||||||
|
id: item_0000
|
||||||
|
width: 320
|
||||||
|
height: 120
|
||||||
|
ShaderEffect {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: 10
|
||||||
|
width: 200
|
||||||
|
height: 100
|
||||||
|
cullMode: model.bar
|
||||||
|
property variant frontSource: front
|
||||||
|
property variant backSource: back
|
||||||
|
fragmentShader: "qrc:shaders/culling.frag.qsb"
|
||||||
|
transform: Rotation {
|
||||||
|
origin.x: 200
|
||||||
|
origin.y: 180 - 120 * index
|
||||||
|
axis { x: 0; y: 1; z: 0 }
|
||||||
|
angle: (turned == true) ? 180 : 0
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
font.pointSize: 10
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: 5
|
||||||
|
text: foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: topLevel
|
||||||
|
width: 320
|
||||||
|
height: 480
|
||||||
|
|
||||||
|
// Make it a layer. Important because the winding order inverts based on the transforms the vertex shader does.
|
||||||
|
// The output should match culling_2 regardless.
|
||||||
|
layer.enabled: true
|
||||||
|
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: front
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "cornflowerblue"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Front"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: back
|
||||||
|
visible: false
|
||||||
|
smooth: true
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: 256
|
||||||
|
height: 64
|
||||||
|
color: "firebrick"
|
||||||
|
radius: 8
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Back"
|
||||||
|
font.pixelSize: 48
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
Repeater {
|
||||||
|
model: ListModel {
|
||||||
|
ListElement {
|
||||||
|
foo: "No culling"
|
||||||
|
bar: ShaderEffect.NoCulling
|
||||||
|
turned: true
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Back-face culling"
|
||||||
|
bar: ShaderEffect.BackFaceCulling
|
||||||
|
turned: true
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
foo: "Front-face culling"
|
||||||
|
bar: ShaderEffect.FrontFaceCulling
|
||||||
|
turned: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item{
|
||||||
|
id: item_0000
|
||||||
|
width: 320
|
||||||
|
height: 120
|
||||||
|
ShaderEffect{
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: 10
|
||||||
|
width: 200
|
||||||
|
height: 100
|
||||||
|
cullMode: model.bar
|
||||||
|
property variant frontSource: front
|
||||||
|
property variant backSource: back
|
||||||
|
fragmentShader: "qrc:shaders/culling.frag.qsb"
|
||||||
|
transform: Rotation {
|
||||||
|
origin.x: 100
|
||||||
|
origin.y: 180 - 120 * index
|
||||||
|
axis { x: 0; y: 1; z: 0 }
|
||||||
|
angle: (turned == true) ? 180 : 0
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
font.pointSize: 10
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: 5
|
||||||
|
text: foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue