aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-06-03 11:26:58 +0200
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-06-03 10:24:32 +0000
commit446661a199563b13db56aeddb7eeecf7259786d8 (patch)
tree88007ab9b4e6f9c58f188d6992266998cf98f42c
parent0e767eaa29ea0a7edb101ba87fb8367e9f056eed (diff)
Enhance rendernode example with opacity support
The opacity is already animated in the QML scene but enabling blending and using inheritedOpacity() was not done. Until now. Change-Id: Iaaf50c20302e29db85c5dfaeaab4d069cb18714e Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.cpp42
-rw-r--r--examples/quick/scenegraph/rendernode/main.qml4
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.cpp16
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.h2
-rw-r--r--examples/quick/scenegraph/rendernode/shader.hlsl7
5 files changed, 49 insertions, 22 deletions
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
index 3694c6ae75..bc03720407 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
@@ -83,7 +83,7 @@ void D3D12RenderNode::init()
D3D12_ROOT_PARAMETER rootParameter;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+ rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
rootParameter.Descriptor.ShaderRegister = 0; // b0
rootParameter.Descriptor.RegisterSpace = 0;
@@ -123,11 +123,19 @@ void D3D12RenderNode::init()
rastDesc.CullMode = D3D12_CULL_MODE_BACK;
rastDesc.FrontCounterClockwise = TRUE; // Vertices are given CCW
- // No blending, just enable color write.
- D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = {};
- defaultRenderTargetBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+ // Enable color write and blending (premultiplied alpha). The latter is
+ // needed because the example changes the item's opacity and we pass
+ // inheritedOpacity() into the pixel shader. If that wasn't the case,
+ // blending could have stayed disabled.
+ const D3D12_RENDER_TARGET_BLEND_DESC premulBlendDesc = {
+ TRUE, FALSE,
+ D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
+ D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
+ D3D12_LOGIC_OP_NOOP,
+ D3D12_COLOR_WRITE_ENABLE_ALL
+ };
D3D12_BLEND_DESC blendDesc = {};
- blendDesc.RenderTarget[0] = defaultRenderTargetBlendDesc;
+ blendDesc.RenderTarget[0] = premulBlendDesc;
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
@@ -177,7 +185,7 @@ void D3D12RenderNode::init()
}
vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
- vertexBufferView.StrideInBytes = (2 + 3) * sizeof(float);
+ vertexBufferView.StrideInBytes = vertexBufferSize / 3;
vertexBufferView.SizeInBytes = vertexBufferSize;
bufDesc.Width = 256;
@@ -198,6 +206,14 @@ void D3D12RenderNode::init()
qWarning("Map failed (constant buffer)");
return;
}
+
+ float *vp = reinterpret_cast<float *>(vbPtr);
+ vp += 2;
+ *vp++ = 1.0f; *vp++ = 0.0f; *vp++ = 0.0f;
+ vp += 2;
+ *vp++ = 0.0f; *vp++ = 1.0f; *vp++ = 0.0f;
+ vp += 2;
+ *vp++ = 0.0f; *vp++ = 0.0f; *vp++ = 1.0f;
}
void D3D12RenderNode::render(const RenderState *state)
@@ -212,6 +228,8 @@ void D3D12RenderNode::render(const RenderState *state)
const int msize = 16 * sizeof(float);
memcpy(cbPtr, matrix()->constData(), msize);
memcpy(cbPtr + msize, state->projectionMatrix()->constData(), msize);
+ const float opacity = inheritedOpacity();
+ memcpy(cbPtr + 2 * msize, &opacity, sizeof(float));
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
const QPointF p1(0, 0);
@@ -220,15 +238,12 @@ void D3D12RenderNode::render(const RenderState *state)
float *vp = reinterpret_cast<float *>(vbPtr);
*vp++ = p0.x();
*vp++ = p0.y();
- *vp++ = 1.0f; *vp++ = 0.0f; *vp++ = 0.0f;
-
+ vp += 3;
*vp++ = p1.x();
*vp++ = p1.y();
- *vp++ = 0.0f; *vp++ = 1.0f; *vp++ = 0.0f;
-
+ vp += 3;
*vp++ = p2.x();
*vp++ = p2.y();
- *vp++ = 0.0f; *vp++ = 0.0f; *vp++ = 1.0f;
commandList->SetPipelineState(pipelineState.Get());
commandList->SetGraphicsRootSignature(rootSignature.Get());
@@ -237,8 +252,9 @@ void D3D12RenderNode::render(const RenderState *state)
commandList->IASetVertexBuffers(0, 1, &vertexBufferView);
commandList->DrawInstanced(3, 1, 0, 0);
-
- // we won't implement changedStates() since no viewport/scissor/stencil/blend related commands were added
}
+// No need to reimplement changedStates() because no relevant commands are
+// added to the command list in render().
+
#endif // HAS_D3D12
diff --git a/examples/quick/scenegraph/rendernode/main.qml b/examples/quick/scenegraph/rendernode/main.qml
index c647aab88d..a91656dfaa 100644
--- a/examples/quick/scenegraph/rendernode/main.qml
+++ b/examples/quick/scenegraph/rendernode/main.qml
@@ -71,9 +71,9 @@ Item {
NumberAnimation { target: rotation; property: "angle"; to: 80; duration: 1000; easing.type: Easing.InOutCubic }
NumberAnimation { target: rotation; property: "angle"; to: -80; duration: 1000; easing.type: Easing.InOutCubic }
NumberAnimation { target: rotation; property: "angle"; to: 0; duration: 1000; easing.type: Easing.InOutCubic }
- NumberAnimation { target: renderer; property: "opacity"; to: 0.5; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: renderer; property: "opacity"; to: 0.1; duration: 1000; easing.type: Easing.InOutCubic }
PauseAnimation { duration: 1000 }
- NumberAnimation { target: renderer; property: "opacity"; to: 0.8; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: renderer; property: "opacity"; to: 1.0; duration: 1000; easing.type: Easing.InOutCubic }
ParallelAnimation {
NumberAnimation { target: scale; property: "xScale"; to: 1; duration: 1000; easing.type: Easing.InOutBack }
NumberAnimation { target: scale; property: "yScale"; to: 1; duration: 1000; easing.type: Easing.InOutBack }
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.cpp b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
index 27712e13b2..3eff70cb42 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
@@ -57,9 +57,6 @@ OpenGLRenderNode::~OpenGLRenderNode()
releaseResources();
}
-// No need to reimplement changedStates() since our rendering is so simple,
-// without involving any state changes.
-
void OpenGLRenderNode::releaseResources()
{
delete m_program;
@@ -84,8 +81,9 @@ void OpenGLRenderNode::init()
static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
+ "uniform lowp float opacity;\n"
"void main() {\n"
- " gl_FragColor = col;\n"
+ " gl_FragColor = col * opacity;\n"
"}\n";
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
@@ -95,6 +93,7 @@ void OpenGLRenderNode::init()
m_program->link();
m_matrixUniform = m_program->uniformLocation("matrix");
+ m_opacityUniform = m_program->uniformLocation("opacity");
const int VERTEX_SIZE = 6 * sizeof(GLfloat);
@@ -123,6 +122,7 @@ void OpenGLRenderNode::render(const RenderState *state)
m_program->bind();
m_program->setUniformValue(m_matrixUniform, *state->projectionMatrix() * *matrix());
+ m_program->setUniformValue(m_opacityUniform, float(inheritedOpacity()));
m_vbo->bind();
@@ -140,7 +140,15 @@ void OpenGLRenderNode::render(const RenderState *state)
m_program->enableAttributeArray(0);
m_program->enableAttributeArray(1);
+ f->glEnable(GL_BLEND);
+ f->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
f->glDrawArrays(GL_TRIANGLES, 0, 3);
}
+QSGRenderNode::StateFlags OpenGLRenderNode::changedStates() const
+{
+ return BlendState;
+}
+
#endif // QT_NO_OPENGL
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.h b/examples/quick/scenegraph/rendernode/openglrenderer.h
index 3f38faf458..28d528e617 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.h
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.h
@@ -57,6 +57,7 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
+ StateFlags changedStates() const override;
private:
void init();
@@ -64,6 +65,7 @@ private:
QQuickItem *m_item;
QOpenGLShaderProgram *m_program = nullptr;
int m_matrixUniform;
+ int m_opacityUniform;
QOpenGLBuffer *m_vbo = nullptr;
};
diff --git a/examples/quick/scenegraph/rendernode/shader.hlsl b/examples/quick/scenegraph/rendernode/shader.hlsl
index 8b9b9ff9d8..f300fe7aa5 100644
--- a/examples/quick/scenegraph/rendernode/shader.hlsl
+++ b/examples/quick/scenegraph/rendernode/shader.hlsl
@@ -2,15 +2,16 @@ cbuffer ConstantBuffer : register(b0)
{
float4x4 modelview;
float4x4 projection;
+ float opacity;
};
struct PSInput
{
float4 position : SV_POSITION;
- float4 color : COLOR;
+ float3 color : COLOR;
};
-PSInput VS_Simple(float4 position : POSITION, float4 color : COLOR)
+PSInput VS_Simple(float4 position : POSITION, float3 color : COLOR)
{
PSInput result;
@@ -23,5 +24,5 @@ PSInput VS_Simple(float4 position : POSITION, float4 color : COLOR)
float4 PS_Simple(PSInput input) : SV_TARGET
{
- return input.color;
+ return float4(input.color, 1.0) * opacity;
}