// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \example extensions/stenciloutline
    \ingroup quick3d-examples
    \title Qt Quick 3D - Stencil Outline Extension Example
    \examplecategory {3D}
    \brief Demonstrates how the QtQuick3D Render Extension can be used to implement stencil outlining.
    \image stencil_outline.jpg

    This example shows how the QtQuick3D Render Extensions can be used to add support for stencil outlining.

    The first step is to implement the front-end item by creating a new \l {QQuick3DRenderExtension}{Render Extension} item which exposes
    the properties needed to QML.
    In this example we expose 3 properties, a \c target which takes the \l {QtQuick3D::Model}{model} we want to outline,
    the \l {QtQuick3D::Material}{material} we want to use for the outline, and a \c scale value for adjusting the size of the outline.

    \snippet extensions/stenciloutline/outlinerenderextension.h extension front

    The second step is to implement the back-end \l {QSSGRenderExtension}{Render Extension} class, this is the class that contains
    the code that will be run by QtQuick3D.

    For this extension we'll be rendering \c after the built-in color-pass, and we'll want to render as part of the main render pass,
    so we'll return \l {QSSGRenderExtension::RenderStage::PostColor}{PostColor} and \l {QSSGRenderExtension::RenderMode::Main}{Main} in
    in our \l QSSGRenderExtension::stage() and QSSGRenderExtension::mode() functions respectively.

    \snippet extensions/stenciloutline/outlinerenderextension.cpp extension back

    The next function that needs to be implement is QSSGRenderExtension::prepareData(), this function should collect and set-up the data
    this extension will be using for rendering. If there's nothing to render this function should return \c false.

    \snippet extensions/stenciloutline/outlinerenderextension.cpp extension back_prepareData

    If QSSGRenderExtension::prepareData() returned \c true the next function to be called is QSSGRenderExtension::prepareRender().
    In this function we'll set-up the \l {QSSGRhiGraphicsPipelineState}{pipeline state} for our two renderables and tell QtQuick3D to
    prepare the primitives etc. for the renderables by calling QSSGRenderHelpers::prepareRenderables().

    \snippet extensions/stenciloutline/outlinerenderextension.cpp extension back_prepareRender

    When the engine is ready to record the rendering calls for our extension it will call the virtual QSSGRenderExtension::render() function.
    In this example we can simply call QSSGRenderHelpers::renderRenderables() for the two models, they will then
    be rendered just the same way as QtQuick3D would have done internally, only this time with our settings.

    \snippet extensions/stenciloutline/outlinerenderextension.cpp extension back_render

    The \c OutlineRenderExtension is made active by adding it to the \l {QtQuick3D::View3D}{View3D's}
    \l {QtQuick3D::View3D::extensions}{extensions} property.

    \snippet extensions/stenciloutline/Main.qml 1

    Now when a \c model is picked we just need to set the picked \c model as the \c target for the \c OutlineRenderExtension
    to have it rendered with an outline.

    \snippet extensions/stenciloutline/Main.qml 2
 */
