En esta página

Qt 3D Visión general

Qt 3D proporciona un renderizador totalmente configurable que permite a los desarrolladores implementar rápidamente cualquier canal de renderizado que necesiten. Además, Qt 3D proporciona un marco genérico para simulaciones en tiempo casi real más allá del renderizado.

Qt 3D está claramente separado en un núcleo y un número ilimitado de aspectos que pueden implementar cualquier funcionalidad que deseen. Los aspectos interactúan con componentes y entidades para proporcionar algún tipo de funcionalidad. Algunos ejemplos de aspectos son la física, el audio, las colisiones, la inteligencia artificial (IA) y la búsqueda de trayectorias.

Características 3D básicas

Qt 3D es un framework 3D que permite dibujar formas 3D y moverlas, así como mover la cámara. Soporta las siguientes características básicas:

Materiales

Qt 3D tiene un sistema de materiales robusto y muy flexible que permite múltiples niveles de personalización. Se adapta a diferentes enfoques de renderizado en diferentes plataformas o versiones de OpenGL, permite múltiples pasadas de renderizado con diferentes conjuntos de estados, proporciona mecanismos para anular parámetros en diferentes niveles, y permite un fácil cambio de sombreadores. Todo ello desde C++ o mediante enlaces de propiedades QML.

Las propiedades de un tipo Material se pueden mapear fácilmente a través de variables uniformes en un programa de sombreado GLSL que se especifica a su vez en la propiedad de efecto referenciada.

Para ejemplos de uso de materiales, ver los siguientes ejemplos:

Sombreadores

Qt 3D admite todas las etapas programables de renderizado de OpenGL: vértices, control de teselación, evaluación de teselación, geometría y sombreadores de fragmentos. Los sombreadores de cálculo están previstos para una futura versión.

Para ver ejemplos de uso de sombreadores, consulte Qt 3D: Wireframe QML Example.

Mapeado de sombras

Las sombras no están soportadas directamente por OpenGL, pero existen innumerables técnicas que pueden emplearse para generarlas. El mapeado de sombras es sencillo de utilizar para generar sombras de buen aspecto, a la vez que tiene un coste de rendimiento muy pequeño.

El mapeado de sombras se implementa normalmente utilizando un renderizado de dos pasadas. En la primera, se genera la información de las sombras. En la segunda, la escena se genera utilizando una técnica de renderizado concreta, al tiempo que se utiliza la información obtenida en la primera pasada para dibujar las sombras.

La idea que subyace al mapeado de sombras es que sólo se iluminan los fragmentos más cercanos a la luz. Los fragmentos situados detrás de otros fragmentos están ocluidos y, por tanto, en la sombra.

Por lo tanto, en la primera pasada, la escena se dibuja desde el punto de vista de la luz. La información que se almacena es simplemente la distancia del fragmento más cercano en este espacio de luz. En términos de OpenGL, esto corresponde a tener un Framebuffer Object, o FBO, con una textura de profundidad adjunta. De hecho, la distancia desde el ojo es la definición de la profundidad, y la prueba de profundidad por defecto realizada por OpenGL almacenará sólo la profundidad del fragmento más cercano.

Una textura de color adjunta ni siquiera es necesaria, porque no hay necesidad de sombrear fragmentos, sólo de calcular su profundidad.

La siguiente imagen muestra una escena con un plano auto-sombreado y un nudo trébol:

Escena renderizada en 3D que muestra un nudo metálico planeando sobre un avión verde y un avión naranja volando al fondo.

La siguiente imagen muestra una textura de mapa de sombras exagerada de la escena:

Mapa de profundidad en escala de grises de un nudo 3D y un avión

La imagen indica la profundidad almacenada al renderizar la escena desde el punto de vista de la luz. Los colores más oscuros representan una profundidad menor (es decir, más cercana a la cámara). En esta escena, la luz está situada en algún lugar por encima de los objetos de la escena, a la derecha con respecto a la cámara principal (compárese con la primera captura de pantalla). Esto coincide con el hecho de que el avión de juguete está más cerca de la cámara que los demás objetos.

Una vez generado el mapa de sombras, se realiza la segunda pasada de renderizado. En este segundo pase, el renderizado se realiza utilizando la cámara de la escena normal. Aquí se puede utilizar cualquier efecto, como el sombreado Phong. Es importante que el algoritmo del mapa de sombras se aplique en el fragment shader. Es decir, el fragmento que está más cerca de la luz se dibuja iluminado, mientras que los otros fragmentos se dibujan en sombra.

El mapa de sombras generado en la primera pasada proporciona la información necesaria sobre la distancia de los fragmentos a la luz. A continuación, basta con reasignar el fragmento en el espacio de luz, calculando así su profundidad desde el punto de vista de la luz, así como dónde se encuentran sus coordenadas en la textura del mapa de sombras. La textura del mapa de sombras puede entonces muestrearse en las coordenadas dadas y la profundidad del fragmento puede compararse con el resultado del muestreo. Si el fragmento está más lejos, entonces está en la sombra; en caso contrario, está iluminado.

Renderizado por instancias

El renderizado porinstancias es una forma de conseguir que la GPU dibuje muchas copias (instancias) de un objeto base que varía de alguna forma en cada copia. A menudo, en posición, orientación, color, propiedades del material, escala, etc. Qt 3D proporciona una API similar al elemento Qt Quick Repeater . En este caso, el delegado es el objeto base y el modelo proporciona los datos por instancia. Así, mientras que una entidad con un componente Mesh adjunto se transforma finalmente en una llamada a glDrawElements, una entidad con un componente instanced se traducirá en una llamada a glDrawElementsInstanced.

El renderizado por instancias está previsto para una futura versión.

Objetos de memoria intermedia uniforme

Un Uniform Buffer Object (UBO) puede vincularse a programas de sombreado OpenGL para facilitar el acceso a grandes cantidades de datos. Los casos típicos de uso de los UBOs son para conjuntos de parámetros de materiales o iluminación.

Consejos útiles

Algunos consejos de programación muy útiles para el renderizado 3D se pueden encontrar en esta página: Qt 3D Consejos Render Pro.

Renderizador configurable

Para combinar el soporte de las APIs C++ y QML con tener un renderizador totalmente configurable, se introdujo el concepto de framegraph. Mientras que un scenegraph es una descripción basada en datos de qué renderizar, un framegraph es una descripción basada en datos de cómo renderizarlo.

Un framegraph permite a los desarrolladores elegir entre un simple renderizador de avance, incluyendo un pase z-fill, o utilizar un renderizador diferido, por ejemplo. También les da el control sobre cuándo renderizar cualquier objeto transparente, etc. Como todo esto se configura puramente a partir de datos, es muy fácil modificarlo incluso dinámicamente en tiempo de ejecución sin tocar ningún código C++. Es posible extender Qt 3D creando tus propios framegraphs que implementen algoritmos de renderizado personalizados.

Extensiones 3D

Más allá de lo esencial de mostrar contenido 3D en la pantalla, Qt 3D es lo suficientemente extensible y flexible para actuar como anfitrión de los siguientes tipos de extensiones relacionadas con los objetos 3D:

  • Simulación física
  • Detección de colisiones
  • Audio posicional 3D
  • Animación de cuerpos rígidos, esqueletos y objetivos morph
  • Búsqueda de trayectorias y otras IA
  • Selección
  • Partículas
  • Generación de objetos

Rendimiento

Qt 3D está diseñado para rendir bien y escalar con el número de núcleos de CPU disponibles, porque el hardware moderno mejora el rendimiento aumentando el número de núcleos en lugar de la velocidad de reloj base. El uso de varios núcleos funciona bien porque muchas tareas son independientes entre sí. Por ejemplo, las operaciones realizadas por un módulo de búsqueda de rutas no se solapan demasiado con las tareas realizadas por un renderizador, excepto quizá al renderizar información de depuración o estadísticas.

Qt 3D Arquitectura

Los principales casos de uso de Qt 3D son la simulación de objetos en tiempo casi real y la representación del estado de esos objetos en la pantalla. El ejemplo de Space Invaders contiene los siguientes objetos:

Captura de pantalla de un juego de invasores del espacio

  • El cañón de tierra del jugador
  • El suelo
  • Los bloques defensivos
  • Las naves invasoras enemigas
  • El platillo volante enemigo jefe
  • Las balas disparadas por los enemigos y el jugador

En un diseño C++ tradicional, estos tipos de objetos se implementarían normalmente como clases dispuestas en algún tipo de árbol de herencia. Varias ramas en el árbol de herencia podrían añadir funcionalidad adicional a la clase raíz para características como:

  • Acepta entradas del usuario
  • Reproduce un sonido
  • Animación
  • colisionar con otros objetos
  • Se dibuja en la pantalla

Los tipos del ejemplo de Space Invaders pueden clasificarse en función de estas características. Sin embargo, diseñar un árbol de herencia elegante incluso para un ejemplo tan sencillo no es fácil.

Este enfoque y otras variaciones de la herencia presentan una serie de problemas:

  • Las jerarquías de herencia profundas y amplias son difíciles de entender, mantener y ampliar.
  • La taxonomía de la herencia se fija en tiempo de compilación.
  • Cada nivel del árbol de herencia de clases sólo puede clasificar según un único criterio o eje.
  • La funcionalidad compartida tiende a subir por la jerarquía de clases con el tiempo.
  • Es imposible predecir lo que los desarrolladores querrán hacer.

Ampliar árboles de herencia profundos y amplios suele requerir comprender la taxonomía utilizada por el autor original y estar de acuerdo con ella. Por lo tanto, Qt 3D se centra en la agregación en lugar de la herencia como medio para impartir funcionalidad a una instancia de un objeto. En concreto, Qt 3D implementa un Sistema de Componentes de Entidad (ECS).

Utilización de un ECS

En un ECS, una entidad representa un objeto simulado, pero por sí misma carece de cualquier comportamiento o característica específica. Se puede injertar un comportamiento adicional en una entidad haciendo que la entidad agregue uno o más componentes. Cada componente es una porción vertical del comportamiento de un tipo de objeto.

En el ejemplo de Space Invaders, el suelo es una entidad con un componente adjunto que indica al sistema que la entidad necesita renderizado y qué tipo de renderizado necesita. Una nave enemiga invasora del espacio es otra entidad con componentes adjuntos que hacen que la nave sea renderizada, pero también le permiten emitir sonidos, ser colisionada, ser animada y ser controlada por una IA simple.

La entidad del cañón terrestre del jugador tiene componentes similares a los de la nave invasora espacial enemiga, excepto que no tiene el componente de IA. En su lugar, el cañón tiene un componente de entrada que permite al jugador moverlo y disparar balas.

ECS Backend

Diagrama de los componentes de QEntity

El backend de Qt 3D implementa la parte de sistema del paradigma ECS en forma de aspectos. Un aspecto implementa la porción vertical particular de la funcionalidad proporcionada a las entidades por una combinación de uno o más de sus componentes agregados.

Por ejemplo, el aspecto renderizador busca entidades que tengan componentes de malla, material y, opcionalmente, transformación. Si el aspecto renderizador encuentra una entidad de este tipo, sabe cómo tomar esos datos y dibujar algo bonito a partir de ellos. Si una entidad no tiene esos componentes, el aspecto renderizador la ignora.

Qt 3D construye entidades personalizadas agregando componentes que proporcionan capacidades adicionales. El motor Qt 3D utiliza aspectos para procesar y actualizar entidades con componentes específicos.

Por ejemplo, un aspecto de física busca entidades que tengan algún tipo de componente de volumen de colisión y otro componente que especifique otras propiedades necesarias para este tipo de simulaciones, como la masa, el coeficiente de fricción, etcétera. Una entidad que emite sonido tiene un componente que especifica que es un emisor de sonido, así como cuándo y qué sonidos reproducir.

Dado que ECS utiliza la agregación en lugar de la herencia, es posible cambiar dinámicamente el comportamiento de un objeto en tiempo de ejecución simplemente añadiendo o eliminando componentes.

Por ejemplo, para que un jugador pueda atravesar paredes repentinamente tras un encendido, el componente de volumen de colisión de esa entidad puede eliminarse temporalmente, hasta que se agote el tiempo de encendido. No es necesario crear una subclase especial para PlayerWhoRunsThroughWalls.

Qt 3D Implementación de ECS

Qt 3D implementa ECS como una simple jerarquía de clases. La clase base Qt 3D es Qt3DCore::QNode, que es una subclase de QObject. Qt3DCore::QNode añade a QObject la capacidad de comunicar automáticamente los cambios de propiedades a los aspectos y un ID que es único en toda una aplicación. Los aspectos existen en hilos adicionales y Qt3DCore::QNode simplifica la transferencia de datos entre los objetos de cara al usuario y los aspectos.

Normalmente, las subclases de Qt3DCore::QNode proporcionan datos de soporte adicionales a los que hacen referencia los componentes. Por ejemplo, la clase QShaderProgram especifica el código GLSL que se utilizará al renderizar un conjunto de entidades.

Diagrama que muestra la relación entre QEntity, QComponent, QNode y QObject

Los componentes de Qt 3D se implementan subclasificando Qt3DCore::QComponent y añadiendo los datos necesarios para que el aspecto correspondiente realice su trabajo. Por ejemplo, el componente malla es utilizado por el aspecto renderizador para recuperar los datos por vértice que deben ser enviados a través del canal OpenGL.

Por último, Qt3DCore::QEntity es simplemente un objeto que puede agregar cero o más instancias de Qt3DCore::QComponent.

Ampliación de Qt 3D

Añadir funcionalidad a Qt 3D, ya sea como parte de Qt o específica de tus propias aplicaciones para beneficiarte del back-end multi-hilo consiste en las siguientes tareas:

  • Identificar e implementar los componentes necesarios y los datos de apoyo.
  • Registrar los componentes con el motor QML (sólo si se utiliza la API QML).
  • Subclase QAbstractAspect e implementar la funcionalidad del subsistema.

Qt 3D Motor basado en tareas

En Qt 3D, se solicita a los aspectos en cada trama un conjunto de tareas para ejecutar junto con las dependencias entre ellas. Las tareas se distribuyen entre todos los núcleos configurados mediante un planificador para mejorar el rendimiento.

Qt 3DAspectos

Por defecto, Qt 3D proporciona los aspectos Qt3DRender y Qt3DInput. Los componentes y otras clases de soporte proporcionadas por estos aspectos se discuten en la documentación de esos módulos.

En futuras versiones de Qt 3D se añadirán aspectos adicionales que proporcionen más capacidades.

© 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.