From 446661a199563b13db56aeddb7eeecf7259786d8 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 3 Jun 2016 11:26:58 +0200 Subject: 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 --- .../quick/scenegraph/rendernode/d3d12renderer.cpp | 42 +++++++++++++++------- examples/quick/scenegraph/rendernode/main.qml | 4 +-- .../quick/scenegraph/rendernode/openglrenderer.cpp | 16 ++++++--- .../quick/scenegraph/rendernode/openglrenderer.h | 2 ++ examples/quick/scenegraph/rendernode/shader.hlsl | 7 ++-- 5 files changed, 49 insertions(+), 22 deletions(-) (limited to 'examples') 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(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(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; } -- cgit v1.2.3