En esta página

Qt Quick 3D - Ejemplo de pases de usuario

Demuestra la creación de pases de renderizado personalizados en Qt Quick 3D.

Una escena 3D renderizada con pases de usuario personalizados

}

El ejemplo de Pases de Usuario demuestra como crear pases de render personalizados en Qt Quick 3D. Muestra una escena 3D simple renderizada usando múltiples pases de render definidos por el usuario para lograr una técnica de iluminación diferida simplificada.

Desactivación de los pases de render internos

Por defecto, Qt Quick 3D utiliza un conjunto de pases de render internos para renderizar la escena 3D. A veces puede que quieras desactivar estos pases internos e implementar tu propia línea de renderizado utilizando pases de render definidos por el usuario.

Para desactivar los pases internos de renderizado, establece la propiedad renderOverrides de View3D a View3D.DisableInternalPasses.

View3D {
    id: view3D
    anchors.fill: parent
    renderOverrides: View3D.DisableInternalPasses
    environment: SceneEnvironment {
        lightProbe: Texture {
            textureData: ProceduralSkyTextureData {
            }
        }
        backgroundMode: SceneEnvironment.SkyBox
    }

Si desactiva los pases internos de renderizado, necesitará proporcionar el resultado del pase de color principal para que View3D pueda mostrar algo en la pantalla.

Pase del búfer de geometría

En este ejemplo, el primer pase de render personalizado es un pase de búfer de geometría (G-buffer) que renderiza la geometría de la escena en múltiples objetivos de render, almacenando diferentes propiedades de material en cada objetivo. El ejemplo proporcionado es un subconjunto de todas las propiedades de material proporcionadas por Qt Quick 3D materials, centrándose en las propiedades necesarias para una implementación básica de iluminación diferida.

Nuestro RenderPass está definido en GBufferPass.qml:

RenderPass {
    id: gbufferPass
    clearColor: Qt.rgba(0.0, 0.0, 0.0, 0.0)

    property alias layerMask: filter.layerMask
    required property RenderPassTexture depthTexture

    RenderPassTexture {
        id: gbuffer0
        format: RenderPassTexture.RGBA16F
        // rgb: baseColor (linear), a: metalness
    }

    RenderPassTexture {
        id: gbuffer1
        format: RenderPassTexture.RGBA16F
        // rgb: normal, a: roughness
    }

    RenderPassTexture {
        id: gbuffer2
        format: RenderPassTexture.RGBA16F
        // rgb: emissive, a: ao/spare
    }

    commands: [
        ColorAttachment { target: gbuffer0; name: "GBUFFER0" },
        ColorAttachment { target: gbuffer1; name: "GBUFFER1" },
        ColorAttachment { target: gbuffer2; name: "GBUFFER2" },
        DepthTextureAttachment { target: gbufferPass.depthTexture },
        RenderablesFilter {
            id: filter
            renderableTypes: RenderablesFilter.Opaque
        }
    ]

    materialMode: RenderPass.AugmentMaterial
    augmentShader: "gbuffer_augment.glsl"
}

Define 3 adjuntos de color y 1 adjunto de profundidad. El pase requiere 3 texturas que se definen como objetos RenderPassTexture dentro de RenderPass. Estas 3 RenderPassTextures se utilizan como objetivos para los adjuntos de color del pase, y el adjunto de profundidad utiliza una textura de profundidad proporcionada desde fuera del pase.

El propio RenderPass está configurado en modo AugmentMaterial, lo que significa que aumentará los materiales de los objetos renderizados con código shader adicional. El shader de aumento se proporciona en el archivo gbuffer_augment.glsl, que emite las propiedades de material requeridas a los múltiples objetivos de renderizado.

void MAIN_FRAGMENT_AUGMENT()
{
    vec3 baseColor   = BASE_COLOR.rgb;
    float metalness  = METALNESS;
    float roughness  = ROUGHNESS;
    vec3 worldNormal = normalize(WORLD_NORMAL);

    // GBuffer 0: albedo + metalness
    GBUFFER0 = vec4(baseColor, metalness);

    // GBuffer 1: normal (encoded to 0..1) + roughness
    GBUFFER1 = vec4(worldNormal * 0.5 + 0.5, roughness);

    // GBuffer 2: world position
    GBUFFER2 = vec4(qt_varWorldPos, 1.0);
}

Aquí puedes ver como el color base, metalness, worldNormal, roughness y la posición del mundo se almacenan en los 3 anexos de color del G-buffer.

Para utilizar realmente el G-buffer pass en el pipeline de renderizado, necesitamos crear una instancia del mismo en Main.qml, y proporcionar la textura de profundidad requerida:

RenderPassTexture {
    id: mainDepthStencilTexture
    format: RenderPassTexture.Depth24Stencil8
}
GBufferPass {
    id: gbufferPass
    layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
    depthTexture: mainDepthStencilTexture
}

RenderOutputProvider {
    id: gbuffer0Provider
    textureSource: RenderOutputProvider.UserPassTexture
    renderPass: gbufferPass
    attachmentSelector: RenderOutputProvider.Attachment0
}

RenderOutputProvider {
    id: gbuffer1Provider
    textureSource: RenderOutputProvider.UserPassTexture
    renderPass: gbufferPass
    attachmentSelector: RenderOutputProvider.Attachment1
}

RenderOutputProvider {
    id: gbuffer2Provider
    textureSource: RenderOutputProvider.UserPassTexture
    renderPass: gbufferPass
    attachmentSelector: RenderOutputProvider.Attachment2
}

Se crean tres instancias de RenderPassTexture para proporcionar referencias a las texturas G-buffer renderizadas, que se utilizarán en el pase de iluminación posterior.

La propiedad layerMask del G-buffer pass se establece para renderizar sólo los objetos que están en ContentLayer.Layer0 y ContentLayer.Layer1. Esto nos permite controlar qué objetos se renderizan en el pase de G-buffer configurando su propiedad layers en consecuencia.

Pase de iluminación diferida

El segundo pase de render personalizado es un pase de iluminación diferida que utiliza los datos almacenados en el G-buffer para calcular la iluminación de la escena. Este pase renderiza un quad a pantalla completa que muestrea las texturas del G-buffer y aplica los cálculos de iluminación en el fragment shader.

El pase de iluminación diferida se define en Main.qml como sigue:

Model {
    id: deferredLightingQuad
    layers: ContentLayer.Layer13
    castsShadows: false
    receivesShadows: false
    geometry: PlaneGeometry {
        // geometry doesn't matter, just need 4 verts
        plane: PlaneGeometry.XY
    }
    materials: [
        CustomMaterial {
            id: lightingPassMaterial
            property TextureInput gbuffer0: TextureInput {
                enabled: true
                texture: Texture {
                    textureProvider: gbuffer0Provider
                }
            }
            property TextureInput gbuffer1: TextureInput {
                enabled: true
                texture: Texture {
                    textureProvider: gbuffer1Provider
                }
            }
            property TextureInput gbuffer2: TextureInput {
                enabled: true
                texture: Texture {
                    textureProvider: gbuffer2Provider
                }
            }
            shadingMode: CustomMaterial.Unshaded
            fragmentShader: "lighting.frag"
            vertexShader: "lighting.vert"
        }
    ]
}

RenderPass {
    id: deferredLightingPass

    readonly property Texture gbuffer0: Texture { textureProvider: gbuffer0Provider }
    readonly property Texture gbuffer1: Texture { textureProvider: gbuffer1Provider }
    readonly property Texture gbuffer2: Texture { textureProvider: gbuffer2Provider }

    materialMode: RenderPass.OriginalMaterial

    commands: [
        ColorAttachment { target: mainColorTexture },
        DepthStencilAttachment {},
        RenderablesFilter { layerMask: ContentLayer.Layer13 }
    ]

}

El modelo deferredLightingQuad utiliza un CustomMaterial con sombreadores de vértices y fragmentos definidos en los archivos lighting.vert y lighting.frag. El CustomMaterial tiene tres propiedades TextureInput que son usadas para pasar las texturas G-buffer a los shaders.

El deferredLightingPass RenderPass renderiza el quad de pantalla completa a la textura de color principal del View3D. Utiliza un RenderablesFilter para renderizar sólo los objetos en ContentLayer. Layer13, que es donde está colocado el deferredLightingQuad Model.

Renderizado en pantalla

Finalmente, para mostrar el resultado de nuestros pases de renderizado personalizados en la pantalla, necesitamos asegurarnos de que la textura de color principal de View3D se actualiza con el resultado del pase de iluminación diferida.

SimpleQuadRenderer {
    texture: Texture {
        textureProvider: mainColorTextureProvider
    }
}

RenderPassTexture {
    id: mainColorTexture
    format: RenderPassTexture.RGBA16F
}

RenderOutputProvider {
    id: mainColorTextureProvider
    textureSource: RenderOutputProvider.UserPassTexture
    renderPass: deferredLightingPass
    attachmentSelector: RenderOutputProvider.Attachment0
}

Aquí se utiliza el SimpleQuadRenderer para renderizar la textura de color principal de View3D utilizando la textura proporcionada por deferredLightingPass.

Este es un ejemplo muy simplificado del uso de pases de usuario personalizados en Qt Quick 3D.

Proyecto de ejemplo @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.