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

/*!
    \example userpasses
    \ingroup quick3d-examples
    \title Qt Quick 3D - User Passes Example
    \examplecategory {3D}
    \brief Demonstrates creating custom render passes in Qt Quick 3D.
    \image userpasses.webp
           {A 3D scene rendered using custom user passes}}

    The \e {User Passes} example demonstrates how to create custom render passes
    in Qt Quick 3D. It implements a deferred lighting rendering pipeline using
    multiple user-defined render passes and shows how to handle the complete
    rendering sequence: opaque geometry, skybox, 2D items embedded in the scene,
    and transparent geometry.

    \section1 Disabling internal render passes

    By default, Qt Quick 3D uses a set of internal render passes to render the
    3D scene. Sometimes you may want to disable these internal passes and
    implement your own rendering pipeline using user-defined render passes.

    To disable the internal render passes, set the \l {QtQuick3D::View3D::renderOverrides}{renderOverrides}
    property of the \l {QtQuick3D::View3D}{View3D} to \c View3D.DisableInternalPasses.

    \snippet userpasses/Main.qml disable internal passes

    If you disable the internal render passes, you will need to provide the result
    of the main color pass for the View3D to be able to display anything on the screen.

    \section1 Geometry Buffer Pass

    In this example, the first custom render pass is a geometry buffer (G-buffer) pass
    that renders the scene geometry into multiple render targets, storing different
    material properties in each target.  The provided example is a subset of the full
    material properties provided by Qt Quick 3D materials, focusing on the properties
    needed for a basic deferred lighting implementation.

    Our RenderPass is defined in \c GBufferPass.qml:

    \snippet userpasses/GBufferPass.qml gbuffer pass

    It defines 3 color attachments and 1 depth attachment. The pass requires 3 textures
    which are defined as \l {QtQuick3D::RenderPassTexture}{RenderPassTexture} objects inside the RenderPass.
    These 3 RenderPassTextures are used as the targets for the color attachments of the pass, and the depth
    attachment uses a depth texture provided from outside the pass.

    The RenderPass itself is set to \c AugmentMaterial mode, which means that it will augment the materials
    of the rendered objects with additional shader code. The augment shader is provided
    in the \c gbuffer_augment.glsl file, which outputs the required material properties
    to the multiple render targets.

    \snippet userpasses/gbuffer_augment.glsl gbuffer augment shader

    Here you see how the base color, metalness, worldNormal, roughness and world position are
    stored into the 3 color attachments of the G-buffer.

    To actually use the G-buffer pass in the rendering pipeline, we need to create an instance
    of it in \c Main.qml, and provide the required depth texture:

    \snippet userpasses/Main.qml depth texture

    \snippet userpasses/Main.qml GBufferPass usage

    Three \l {QtQuick3D.Helpers::}{RenderOutputProvider} instances are created to provide
    references to the rendered G-buffer textures, which will be used in the subsequent lighting pass.

    The \c layerMask property of the G-buffer pass is set to only render objects
    that are on ContentLayer.Layer0 and ContentLayer.Layer1. This allows us to control
    which objects are rendered in the G-buffer pass by setting their \l {QtQuick3D::Model::layers}{layers}
    property accordingly.

    \section1 Main Color Pass and SubRenderPasses

    Rather than a single flat render pass, this example uses a composite \c mainColorPass
    that owns the main color and depth textures and orchestrates all rendering through
    a sequence of \l {QtQuick3D::SubRenderPass}{SubRenderPass} children.

    Each SubRenderPass shares the same render targets as the outer pass and executes
    in order. This makes it straightforward to build a layered rendering pipeline where
    each stage adds to the result of the previous one.

    \snippet userpasses/Main.qml main color pass

    The outer pass sets \c renderableTypes: RenderablesFilter.None so that nothing
    renders directly in the parent pass — all rendering is delegated to the
    sub-passes. The \c PreserveDepthStencilContents flag ensures that depth values
    written by the G-buffer pass are available to every sub-pass.

    \section2 Deferred Lighting SubPass

    The first sub-pass runs the deferred lighting computation. It renders
    the full-screen \c deferredLightingQuad model which samples the G-buffer
    textures and evaluates lighting for every pixel.

    \snippet userpasses/Main.qml deferred lighting quad

    The \c deferredLightingQuad is placed on \c ContentLayer.Layer13 so that it is
    invisible to the G-buffer pass and only rendered by this sub-pass.

    A \l {QtQuick3D::PipelineStateOverride}{PipelineStateOverride} disables both
    depth writes and depth tests for the quad. The G-buffer pass already wrote correct
    depth for the scene geometry, so the full-screen quad must not alter or test depth.

    \section2 Skybox SubPass

    The second sub-pass renders the scene environment skybox using the special
    \c RenderPass.SkyboxPass pass mode. Qt Quick 3D takes care of drawing the
    skybox geometry using the \l {QtQuick3D::SceneEnvironment::lightProbe}{lightProbe}
    and \l {QtQuick3D::SceneEnvironment::backgroundMode}{backgroundMode} settings from
    the \l {QtQuick3D::SceneEnvironment}{SceneEnvironment}.

    A PipelineStateOverride enables depth testing so the skybox is correctly hidden
    behind scene geometry, while depth writes are disabled because the skybox sits "at
    infinity" and must never occlude geometry.

    \section2 Transparent Objects SubPass

    Transparent objects cannot be stored in the G-buffer because they require
    back-to-front sorted blending. Instead they are rendered last using their
    original materials via a dedicated sub-pass.

    The transparent cone in the scene is declared as follows:

    \snippet userpasses/Main.qml transparent cone

    The transparent sub-pass uses a \l {QtQuick3D::RenderablesFilter}{RenderablesFilter}
    to select only transparent renderables on the matching layers, and a
    PipelineStateOverride enables alpha blending while keeping depth testing active
    so transparent objects sort correctly against opaque geometry.

    Transparent objects must be rendered \e after all opaque passes so that the
    depth buffer is fully populated before blending occurs.

    \section2 2D Items in 3D SubPass

    Qt Quick 3D can embed standard Qt Quick 2D items inside the 3D scene using
    \l {QtQuick3D::Node}{Node} as a container. To include these items in a custom
    render pipeline, add a sub-pass with \c passMode: RenderPass.Item2DPass.

    \snippet userpasses/Main.qml item2d node

    The \c Item2DPass mode instructs Qt Quick 3D to render all Qt Quick items
    that are children of 3D nodes into the current render target, composited with
    the 3D content already present.

    \section1 Rendering to the screen

    Finally, to display the result of our custom render passes on the screen,
    we need to ensure that the View3D's main color texture is updated with the
    result of the main color pass.

    \snippet userpasses/Main.qml main texture

    The \l {QtQuick3D.Helpers::}{SimpleQuadRenderer} is used to blit the
    main color texture produced by the \c mainColorPass to the View3D's framebuffer.
    The \l {QtQuick3D.Helpers::}{RenderOutputProvider} exposes the first
    color attachment of \c mainColorPass as a texture the SimpleQuadRenderer can
    sample.
*/
