En esta página

CustomMaterial QML Type

Componente base para crear materiales personalizados utilizados para sombrear modelos. Más...

Import Statement: import QtQuick3D
Inherits:

Material

Propiedades

Descripción detallada

El material personalizado permite utilizar código shader personalizado para un material, permitiendo la programabilidad a nivel de shader gráfico. Se puede proporcionar un sombreador de vértices, de fragmentos o ambos. Las propiedades vertexShader y fragmentShader son URLs, referenciando archivos que contienen fragmentos de shaders, y funcionan de forma muy similar a ShaderEffect o Image.source. Sólo los esquemas file y qrc son compatibles con materiales personalizados. También es posible omitir el esquema file, permitiendo especificar una ruta relativa de forma conveniente. Dicha ruta se resuelve de forma relativa a la ubicación del componente (el archivo .qml ).

Para obtener una guía de iniciación a los materiales personalizados, consulte la página Materiales programables, efectos, geometría y datos de textura.

Introducción

Considere las siguientes versiones de la misma escena. A la izquierda, el cilindro utiliza un material incorporado, no programable. Tales materiales son configurables a través de una amplia gama de propiedades, pero no hay más control sobre los shaders que se generan bajo el capó. A la derecha, el mismo cilindro se asocia ahora con un CustomMaterial que hace referencia a los fragmentos de sombreado de vértices y fragmentos proporcionados por la aplicación. Esto permite insertar lógica personalizada específica de la aplicación en el sombreador de vértices para transformar la geometría y determinar ciertas propiedades de color de forma personalizada en el sombreador de fragmentos. Como se trata de un material personalizado de shaded, el cilindro sigue participando normalmente en la iluminación de la escena.

View3D {
    anchors.fill: parent
    PerspectiveCamera {
        id: camera
        position: Qt.vector3d(0, 0, 600)
    }
    camera: camera
    DirectionalLight {
        position: Qt.vector3d(-500, 500, -100)
        color: Qt.rgba(0.2, 0.2, 0.2, 1.0)
        ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
    }
    Model {
        source: "#Cylinder"
        eulerRotation: Qt.vector3d(30, 30, 0)
        scale: Qt.vector3d(1.5, 1.5, 1.5)
        materials: [
            DefaultMaterial {
                diffuseColor: Qt.rgba(0, 1, 0, 1)
            }
        ]
    }
}
View3D {
    anchors.fill: parent
    PerspectiveCamera {
        id: camera
        position: Qt.vector3d(0, 0, 600)
    }
    camera: camera
    DirectionalLight {
        position: Qt.vector3d(-500, 500, -100)
        color: Qt.rgba(0.2, 0.2, 0.2, 1.0)
        ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
    }
    Model {
        source: "#Cylinder"
        eulerRotation: Qt.vector3d(30, 30, 0)
        scale: Qt.vector3d(1.5, 1.5, 1.5)
        materials: [
            CustomMaterial {
                vertexShader: "material.vert"
                fragmentShader: "material.frag"
                property real uTime
                property real uAmplitude: 50
                NumberAnimation on uTime { from: 0; to: 100; duration: 10000; loops: -1 }
            }
        ]
    }
}

Supongamos que los fragmentos del shader en material.vert y material.frag son los siguientes:

void MAIN()
{
    VERTEX.x += sin(uTime + VERTEX.y) * uAmplitude;
}
void MAIN()
{
    BASE_COLOR = vec4(0.0, 1.0, 0.0, 1.0);
}

Observa como uTime y uAmplitude son propiedades del elemento CustomMaterial. Pueden cambiar valores y animarse normalmente, los valores serán expuestos a los shaders automáticamente sin ninguna acción adicional del desarrollador.

El resultado es un cilindro que anima sus vértices:

Cilindro curvado con sombreador de vértices personalizado

Dos tipos de materiales personalizados

Hay dos tipos principales de materiales personalizados. Esto se especifica mediante la propiedad shadingMode. En los materiales personalizados unshaded el sombreador de fragmentos produce un único color vec4, ignorando luces, sondas de luz y sombras en la escena. En los materiales de shaded se espera que el shader implemente ciertas funciones y trabaje con variables incorporadas para tener en cuenta la contribución de la iluminación y las sombras.

La elección por defecto suele ser un material sombreado, esto se refleja en el valor por defecto de la propiedad shadingMode. Esto se ajusta a los materiales que necesitan transformar vértices u otros datos entrantes de la geometría, o determinar valores como BASE_COLOR o EMISSIVE_COLOR de forma personalizada, quizás muestreando SCREEN_TEXTURE o DEPTH_TEXTURE, mientras siguen recibiendo contribuciones de luz y sombra de la escena. Además, estos materiales también pueden anular y reimplementar las ecuaciones utilizadas para calcular las contribuciones de las luces direccionales, puntuales y otras. Los fragmentos de sombreado proporcionados por la aplicación son modificados en gran medida por el motor 3D de Qt Quick con el fin de proporcionar las características, como la iluminación, que tienen los materiales estándar.

Los materiales sin sombreado son útiles cuando el aspecto del objeto viene determinado completamente por el código de sombreado personalizado. Los shaders para tales materiales reciben adiciones mínimas por el motor, y por lo tanto es completamente hasta el shader para determinar el color del fragmento final. Esto da más libertad, pero también limita las posibilidades de integración con otros elementos de la escena, como las luces.

Nota: El código del sombreador siempre se proporciona utilizando GLSL al estilo Vulkan, independientemente de la API gráfica utilizada por Qt en tiempo de ejecución.

Nota: El código de sombreado de vértices y fragmentos proporcionado por el material no son sombreadores GLSL completos por sí mismos. Más bien, proporcionan un conjunto de funciones, que luego son modificadas con más código shader por el motor.

Exposición de datos a los sombreadores

Las propiedades dinámicas del CustomMaterial se pueden cambiar y animar utilizando QML y Qt Quick, y los valores se exponen automáticamente a los shaders. Esto en la práctica es muy similar ShaderEffect. La siguiente lista muestra cómo se asignan las propiedades:

  • bool, int, real -> bool, int, float
  • QColor color -> vec4, y el color se convierte a lineal, asumiendo el espacio sRGB para el valor de color especificado en QML. Los colores Qt incorporados, como también están en espacio de color sRGB, y la misma conversión se realiza para todas las propiedades de color de DefaultMaterial y , por lo que este comportamiento de CustomMaterial coincide con ellos. A diferencia de , para la linealización 3D es esencial ya que normalmente se realizará tonemapping en la escena 3D. "green" PrincipledMaterial Qt Quick Qt Quick
  • QRect QRectF, -> vec4 rect
  • QPoint QPointF, , , , -> vec2 point QSize QSizeF size
  • QVector2D vector2d -> vec2
  • QVector3D, vector3d -> vec3
  • QVector4D, vector4d -> vec4
  • QMatrix4x4, matrix4x4 -> mat4
  • QQuaternion, quaternion -> vec4, valor escalar es w
  • TextureInput -> sampler2D o samplerCube, dependiendo de si se utiliza Texture o CubeMapTexture en la propiedad texture del TextureInput. Establecer la propiedad enabled a false lleva a exponer una textura ficticia al shader, lo que significa que los shaders siguen siendo funcionales pero muestrearán una textura con contenido de imagen negra opaca. Presta atención al hecho de que las propiedades para los muestreadores siempre deben hacer referencia a un objeto TextureInput, no a un Texture directamente. En lo que respecta a las propiedades de Texture, las relacionadas con la fuente, el mosaico y el filtrado son las únicas que se tienen en cuenta de forma implícita con los materiales personalizados, ya que el resto (como las transformaciones UV) depende de los sombreadores personalizados para que las implementen como consideren oportuno.

Nota: Cuando un uniforme referenciado en el código del shader no tiene una propiedad correspondiente, causará un error de compilación del shader al procesar el material en tiempo de ejecución. Hay algunas excepciones a esto, como los uniformes sampler, que obtienen una textura ficticia cuando no hay una propiedad QML correspondiente, pero como regla general, todos los uniformes y samplers deben tener una propiedad correspondiente declarada en el objeto CustomMaterial.

Materiales personalizados sin sombreado

A continuación se muestra un ejemplo de material personalizado unshaded.

CustomMaterial {
    // These properties are automatically exposed to the shaders
    property real time: 0.0
    property real amplitude: 5.0
    property real alpha: 1.0
    property TextureInput tex: TextureInput {
        enabled: true
        texture: Texture { source: "image.png" }
    }

    shadingMode: CustomMaterial.Unshaded
    sourceBlend: alpha < 1.0 ? CustomMaterial.SrcAlpha : CustomMaterial.NoBlend
    destinationBlend: alpha < 1.0 ? CustomMaterial.OneMinusSrcAlpha : CustomMaterial.NoBlend
    cullMode: CustomMaterial.BackFaceCulling

    vertexShader: "customshader.vert"
    fragmentShader: "customshader.frag"
}

Con el ejemplo anterior, los fragmentos de sombreado de vértices y fragmentos de unshaded podrían tener el siguiente aspecto. Nótese como los shaders no declaran, ni deben declarar, uniformes o entradas de vértices ya que de eso se encarga Qt al ensamblar el código final del shader.

VARYING vec3 pos;
VARYING vec2 texcoord;

void MAIN()
{
    pos = VERTEX;
    pos.x += sin(time * 4.0 + pos.y) * amplitude;
    texcoord = UV0;
    POSITION = MODELVIEWPROJECTION_MATRIX * vec4(pos, 1.0);
}
VARYING vec3 pos;
VARYING vec2 texcoord;

void MAIN()
{
    vec4 c = texture(tex, texcoord);
    FRAGCOLOR = vec4(pos.x * 0.02, pos.y * 0.02, pos.z * 0.02, alpha) * c;
}

Están disponibles las siguientes palabras clave especiales en mayúsculas:

  • MAIN -> el nombre del punto de entrada en el fragmento de sombreado de vértices o fragmentos debe ser siempre MAIN. Proporcionar esta función es obligatorio en los fragmentos de shaders para materiales personalizados sin sombreado.
  • VARYING -> declara una salida del vertex shader o una entrada al fragment shader
  • POSITION -> vec4, la salida del vertex shader
  • FRAGCOLOR -> vec4, la salida del fragment shader. Disponible sólo para materiales personalizados sin sombreado.
  • VERTEX -> vec3, la posición del vértice en el sombreador de vértices.
  • NORMAL -> vec3, la normal del vértice en el sombreador de vértices. Cuando la malla del modelo asociado no proporciona normales, el valor es vec3(0.0).
  • UV0 -> vec2, el primer conjunto de coordenadas de textura en el sombreador de vértices. Cuando la malla del modelo asociado no proporciona coordenadas de textura, el valor es vec2(0.0).
  • UV1 -> vec2, el segundo conjunto de coordenadas de textura en el sombreador de vértices. Cuando la malla del modelo asociado no proporciona un segundo conjunto de coordenadas de textura, el valor es vec2(0.0).
  • COLOR -> vec4, el color del vértice en el sombreador de vértices. Cuando la malla del modelo asociado no proporciona colores por vértice, el valor es vec4(1.0).
  • TANGENT -> vec3, tangente en el sombreador de vértices. Cuando la malla del modelo asociado no proporciona datos tangentes, el valor es vec3(0.0).
  • BINORMAL -> vec3, binormal en el sombreador de vértices. Cuando la malla del modelo asociado no proporciona datos binormales, el valor es vec3(0.0).
  • JOINTS -> ivec4, índices de juntas en el sombreador de vértices. Cuando la malla para el modelo asociado no proporciona datos de índices de articulaciones, el valor es ivec4(0).
  • PESOS -> vec4, pesos de las juntas en el sombreador de vértices. Cuando la malla para el modelo asociado no proporciona datos de pesos de articulaciones, el valor es vec4(0.0).
  • MORPH_POSITION(n) -> vec3, la n+1ªposición del objetivo morph en el sombreador de vértices. El modelo asociado debe proporcionar los datos apropiados.
  • MORPH_NORMAL(n) -> vec3, la n+1ªnormal del objetivo morph en el sombreador de vértices. El modelo asociado debe proporcionar los datos apropiados.
  • MORPH_TANGENT(n) -> vec3, el n+1ºobjetivo morph tangente en el sombreador de vértices. El modelo asociado debe proporcionar los datos apropiados.
  • MORPH_BINORMAL(n) -> vec3, el n+1ºobjetivo morph binormal en el sombreador de vértices. El modelo asociado debe proporcionar los datos apropiados.
  • MODELVIEWPROJECTION_MATRIX -> mat4, la matriz modelo-vista-proyección. Las matrices de proyección siempre siguen las convenciones de OpenGL, con una transformación incorporada para la dirección del eje Y y la profundidad del clip, dependiendo de la API gráfica utilizada en tiempo de ejecución.
  • VIEWPROJECTION_MATRIX -> mat4, la matriz de proyección de la vista
  • PROJECTION_MATRIX -> mat4, la matriz de proyección
  • INVERSE_PROJECTION_MATRIX -> mat4, la matriz de proyección inversa
  • VIEW_MATRIX -> mat4, la matriz de vista (cámara)
  • MODEL_MATRIX -> mat4, la matriz del modelo (mundo)
  • NORMAL_MATRIX -> mat3, la matriz normal (la transpuesta de la inversa de la parte superior izquierda 3x3 de la matriz del modelo)
  • BONE_TRANSFORMS -> mat4[], la matriz de las matrices de los huesos del modelo
  • BONE_NORMAL_TRANSFORMS -> mat3[], el array de las matrices normales de los huesos del modelo (la transpuesta de la inversa de la parte superior izquierda 3x3 de las matrices de cada hueso)
  • MORPH_WEIGHTS -> float[], el array de los pesos morph. El modelo asociado debe proporcionar los datos adecuados. Por seguridad, QT_MORPH_MAX_COUNT se define al tamaño de este array.
  • CAMERA_POSITION -> vec3, la posición de la cámara en el espacio global
  • CAMERA_DIRECTION -> vec3, el vector de direccion de la camara
  • CAMERA_PROPERTIES -> vec2, los valores del clip cercano y lejano de la cámara
  • POINT_SIZE -> float, sólo escribible en el sombreador de vértices. Cuando se renderiza geometría con una topología de puntos, el sombreador de vértices personalizado debe establecerlo en 1.0 u otro valor, tanto en materiales personalizados sombreados como no sombreados. Consulte PrincipledMaterial::pointSize para obtener más información sobre la compatibilidad con tamaños distintos de 1.

Materiales personalizados sombreados

Un material shaded augments el código shader que sería generado por un PrincipledMaterial. A diferencia de los materiales sin sombrear, que proporcionan casi toda la lógica para las funciones principales del vertex y fragment shader por sí mismos, evitando añadir código generado para iluminación, sombreado, iluminación global, etc., los materiales sombreados permiten que la generación de shaders se produzca normalmente, como si el CustomMaterial fuera un PrincipledMaterial. Se espera que los fragmentos de shaders de vértices y fragmentos proporcionen funciones opcionales que luego se invocan en determinados puntos, dándoles la posibilidad de personalizar los colores y otros valores que luego se utilizan para calcular la iluminación y el color final del fragmento.

En lugar de implementar sólo una función MAIN, el sombreador de fragmentos de un material personalizado sombreado puede implementar múltiples funciones. Todas las funciones, incluida MAIN, son opcionales en los materiales sombreados personalizados. Un fragmento de sombreado vacío o, incluso, no especificar las propiedades vertexShader o fragmentShader también puede ser perfectamente válido.

Fragmentos de sombreado de vértices en un material personalizado sombreado

Las siguientes funciones pueden implementarse en un fragmento de sombreador de vértices:

  • void MAIN() Cuando está presente, esta función es llamada para establecer el valor de POSITION, la salida vec4 del sombreador de vértices, y, opcionalmente, para modificar los valores de VERTEX, COLOR, NORMAL, UV0, UV1, TANGENT, BINORMAL, JOINTS, y WEIGHTS. A diferencia de los materiales no sombreados, escribir en ellos tiene sentido porque los valores modificados se tienen en cuenta en el resto del código del sombreador generado (mientras que para los materiales no sombreados no se genera código de sombreado adicional). Por ejemplo, si el sombreador de vértices personalizado desplaza los vértices o las normales, querrá almacenar los valores modificados en VERTEX o NORMAL, para conseguir después cálculos de iluminación correctos. Adicionalmente, la función puede escribir en variables definidas con VARYING para pasar datos interpolados al fragment shader. Cuando esta función o una redefinición de POSITION no está presente, POSITION se calcula basándose en VERTEX y MODELVIEWPROJECTION_MATRIX, tal y como haría un PrincipledMaterial.

    Ejemplo, confiando tanto en propiedades QML expuestas como uniformes, y también pasando datos al fragment shader:

    VARYING vec3 vNormal;
    VARYING vec3 vViewVec;
    
    void MAIN()
    {
        VERTEX.x += sin(uTime * 4.0 + VERTEX.y) * uAmplitude;
        vNormal = normalize(NORMAL_MATRIX * NORMAL);
        vViewVec = CAMERA_POSITION - (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
        POSITION = MODELVIEWPROJECTION_MATRIX * vec4(VERTEX, 1.0);
    }

    Nota: En el ejemplo anterior, asignar un valor a POSITION es opcional, ya que el uso en este caso es idéntico al comportamiento por defecto.

Nota: Para pasar datos sin interpolación del vértice a la etapa de fragmento, añada la palabra clave flat antes del tipo en las declaraciones de VARYING.

Fragmentos de sombreado de fragmentos en un material personalizado sombreado

Las siguientes funciones pueden implementarse en un fragmento de sombreado de fragmentos:

  • void MAIN() Cuando está presente, esta función es llamada para establecer los valores de las variables especiales escribibles BASE_COLOR, METALNESS, ROUGHNESS, SPECULAR_AMOUNT, NORMAL, CLEARCOAT_FRESNEL_POWER, CLEARCOAT_FRESNEL_SCALE, CLEARCOAT_FRESNEL_BIAS, CLEARCOAT_AMOUNT, CLEARCOAT_ROUGHNESS, CLEARCOAT_NORMAL, FRESNEL_BIAS, FRESNEL_SCALE, FRESNEL_POWER, IOR, TRANSMISSION_FACTOR, THICKNESS_FACTOR, ATTENUATION_COLOR, ATTENUATION_DISTANCE y OCCLUSION_AMOUNT.

    Un caso de uso común es establecer el valor de BASE_COLOR basándose en el muestreo de una textura, ya sea un mapa de color base, SCREEN_TEXTURE, o algún otro tipo de fuente. Esto puede ser relevante y conveniente especialmente cuando no se implementan funciones personalizadas del procesador de luz. Establecer BASE_COLOR.a a algo distinto del valor por defecto 1.0 permite afectar al valor alfa final del fragmento. (tenga en cuenta que esto a menudo requerirá también activar la mezcla alfa en sourceBlend y destinationBlend)

    Otro escenario es cuando no hay una función personalizada SPECULAR_LIGHT proporcionada, o cuando hay una sonda de luz establecida en el SceneEnvironment. El metal, la rugosidad, y otros valores que afectan el cálculo de la contribución especular se pueden establecer en MAIN a sus valores personalizados deseados.

    La función puede escribir en las siguientes variables especiales. Los valores que se escriben en ellas normalmente se codifican o se calculan basándose en propiedades QML asignadas a uniformes. La semántica es idéntica a la de PrincipledMaterial.

    • vec4 BASE_COLOR - El color base y el valor alfa del material. Corresponde a built-in materials' color property. Cuando las funciones del procesador de luz no están implementadas, puede ser conveniente establecer un color base personalizado en MAIN porque entonces se tiene en cuenta en los cálculos de iluminación por defecto. El valor por defecto es vec4(1.0), es decir, blanco con un alfa de 1.0. El valor alfa afecta al alfa final del fragmento. El valor alfa final es la opacidad del objeto (modelo) multiplicada por el color base alfa. Cuando se especifica el valor directamente en el código del shader, sin depender de los valores uniformes expuestos desde las propiedades de color en QML, tenga en cuenta que depende del shader realizar la conversión de sRGB a lineal, si es necesario. Por ejemplo, suponiendo un vec3 color y float alpha esto se puede lograr de la siguiente manera:
      float C1 = 0.305306011;
      vec3 C2 = vec3(0.682171111, 0.682171111, 0.682171111);
      vec3 C3 = vec3(0.012522878, 0.012522878, 0.012522878);
      BASE_COLOR = vec4(rgb * (rgb * (rgb * C1 + C2) + C3), alpha);
    • vec3 EMISSIVE_COLOR - El color de la auto-iluminación. Corresponde al color emisivo de los materiales incorporados que es combinado por built-in materials's emissiveFactor property y built-in materials's emissiveMap property. El valor por defecto es vec3(0.0). Al especificar el valor directamente en el código del shader, sin depender de los valores uniformes expuestos desde las propiedades de color en QML, tenga en cuenta que depende del shader realizar la conversión de sRGB a lineal, si es necesario.
    • float IOR Especifica el índice de refracción del material. Un valor típico, y también el predeterminado, es 1.5, ya que es el que utilizaría PrincipledMaterial.
    • float TRANSMISSION_FACTOR Especifica la cantidad de translucidez. Un valor típico, sería 1.0 y también el valor por defecto, es 0.0 ya que es lo que usaría un PrincipledMaterial.
    • float THICKNESS_FACTOR Especifica la cantidad de grosor del material translúcido. Un valor típico, sería 10.0 y también el valor por defecto, es 0.0 ya que es lo que usaría un PrincipledMaterial.
    • vec3 ATTENUATION_COLOR Especifica el cambio de color del material translúcido por distancia. Un valor típico, sería vec3(1.0, 0.0, 0.0) y también el valor por defecto, es vec3(1.0) ya que es lo que usaría un PrincipledMaterial.
    • float ATTENUATION_DISTANCE Especifica la atenuación por distancia del cambio de color del material translúcido. Un valor típico, sería 100.0 y también el valor por defecto, es 0.0 ya que es lo que usaría un PrincipledMaterial.
    • float METALNESS Cantidad de metalness en el rango 0.0 - 1.0. El valor por defecto es 0. Debe establecerse en un valor distinto de cero para que tenga efecto.
    • float ROUGHNESS Valor de rugosidad en el rango 0.0 - 1.0. El valor por defecto es 0.
    • float CLEARCOAT_FRESNEL_POWER Especifica el poder fresnel de la capa de barniz. Un valor típico, y también el valor por defecto, es 5.0 ya que es el que utilizaría un PrincipledMaterial.
    • float CLEARCOAT_FRESNEL_SCALE Especifica la escala de fresnel de la capa de barniz. Un valor típico, y también el predeterminado, es 1.0, ya que es el que utilizaría PrincipledMaterial.
    • float CLEARCOAT_FRESNEL_BIAS Especifica el sesgo de fresnel de la capa de barniz. Un valor típico, y también el predeterminado, es 0.0, ya que es el que utilizaría PrincipledMaterial.
    • float CLEARCOAT_AMOUNT Especifica la cantidad de capa de barniz sobre el material. Un valor típico, sería 1.0 y también el valor por defecto, es 0.0 ya que es lo que usaría un PrincipledMaterial.
    • float CLEARCOAT_ROUGHNESS Especifica la rugosidad de la capa de barniz. Un valor típico, sería 1.0 para una capa de barniz totalmente borrosa y también el valor por defecto, es 0.0 ya que es lo que utilizaría un PrincipledMaterial.
    • vec3 CLEARCOAT_NORMAL - La normal de la capa transparente que proviene del sombreador de vértices en el espacio global. Aunque esta propiedad tiene el mismo valor inicial que VAR_WORLD_NORMAL, sólo cambiar el valor de CLEARCOAT_NORMAL tendrá efecto sobre la normal de la capa de capa transparente.
    • float FRESNEL_POWER Especifica la potencia de fresnel. Un valor típico, y también el predeterminado, es 5.0 ya que es el que utilizaría PrincipledMaterial.
    • float FRESNEL_SCALE Especifica la escala de fresnel. Un valor típico, y también el predeterminado, es 1.0, ya que es el que utilizaría PrincipledMaterial.
    • float FRESNEL_BIAS Especifica el sesgo de fresnel. Un valor típico, y también el predeterminado, es 0.0, ya que es el que utilizaría PrincipledMaterial.
    • float SPECULAR_AMOUNT Cantidad especular en el rango 0.0 - 1.0. El valor por defecto es 0.5, que coincide con PrincipledMaterial::specularAmount. Debe establecerse en un valor distinto de cero para que tenga efecto.
    • float OCCLUSION_AMOUNT Especifica el factor AO. Un valor típico, y también el predeterminado, es 1.0 ya que es el que utilizaría PrincipledMaterial.
    • vec3 NORMAL - La normal que proviene del sombreador de vértices en el espacio del mundo. Aunque esta propiedad tiene el mismo valor inicial que VAR_WORLD_NORMAL, sólo cambiando el valor de NORMAL tendrá efecto sobre la iluminación.
    • vec3 TANGENT - La tangente que proviene del sombreador de vértices en el espacio global. Este valor se ajusta potencialmente para la doble cara.
    • vec3 BINORMAL - La binormal que proviene del sombreador de vértices en el espacio global. Este valor está potencialmente ajustado para doble cara.
    • vec2 UV0 - El primer conjunto de coordenadas de textura del sombreador de vértices. Esta propiedad es de solo lectura en el fragment shader.
    • vec2 UV1 - El segundo conjunto de coordenadas de textura del sombreador de vértices. Esta propiedad es de sólo lectura en el sombreador de fragmentos.

    Nota: A diferencia de los materiales no sombreados, el fragmento MAIN para un material sombreado no tiene control directo sobre FRAGCOLOR. Más bien, son los valores DIFFUSE y SPECULAR escritos en las funciones del procesador de luz los que deciden cual es el color final del fragmento. Cuando no se implementa una función de procesador de luz, los cálculos de sombreado por defecto pertinentes se realizan como con un PrincipledMaterial, teniendo en cuenta BASE_COLOR y otros valores de la lista anterior.

    Un ejemplo de sombreador de material personalizado sencillo y metálico podría ser el siguiente:

    void MAIN()
    {
        METALNESS = 1.0;
        ROUGHNESS = 0.5;
        FRESNEL_POWER = 5.0;
    }

    Otro ejemplo, donde el color base y el alfa se establecen muestreando una textura:

    VARYING vec2 texcoord;
    void MAIN()
    {
        BASE_COLOR = texture(uColorMap, texcoord);
    }
  • void AMBIENT_LIGHT() Cuando está presente, esta función es llamada una vez por cada fragmento. La tarea de la función es añadir la contribución total del ambiente a una variable especial escribible DIFFUSE. Por supuesto, se puede optar por calcular un valor diferente, o no tocar DIFFUSE en absoluto (para ignorar por completo la iluminación ambiental). Cuando esta función no está presente en absoluto, la contribución ambiental se calcula normalmente, como lo haría un PrincipledMaterial.

    La función puede escribir en las siguientes variables especiales:

    • vec3 DIFFUSE Acumula las contribuciones de luz difusa, por fragmento. Las funciones del procesador de luz normalmente le añadirán (+=), ya que sobrescribiendo el valor se perdería la contribución de otras luces.

    La función puede leer las siguientes variables especiales, además de las matrices (como, MODEL_MATRIX) y vectores (como, CAMERA_POSITION) uniformes de la tabla anterior:

    • vec3 TOTAL_AMBIENT_COLOR La contribución ambiental total en la escena.

    Ejemplo:

    void AMBIENT_LIGHT()
    {
        DIFFUSE += TOTAL_AMBIENT_COLOR;
    }
  • void DIRECTIONAL_LIGHT() Cuando está presente, esta función es llamada para cada luz direccional activa en la escena para cada fragmento. La tarea de la función es añadir la contribución difusa a una variable especial escribible DIFFUSE. La función también puede elegir no hacer nada, en cuyo caso se ignoran las contribuciones difusas de las luces direccionales. Cuando la función no está presente en absoluto, las contribuciones difusas de las luces direccionales se acumulan normalmente, como haría un PrincipledMaterial.

    La función puede escribir en las siguientes variables especiales:

    • vec3 DIFFUSE Acumula las contribuciones difusas de la luz, por fragmento.
    • Las funciones del procesador de luz normalmente le añadirán (+=
    )
    • , ya que sobreescribiendo el valor se perdería la contribución de otras luces.

    La función puede leer las siguientes variables especiales, además de las matriciales (como, MODEL_MATRIX

    )

    y vectoriales (como, CAMERA_POSITION

    )

    uniformes de la tabla anterior:

    • vec3 LIGHT_COLOR Color de luz difusa.
    • float SHADOW_CONTRIB Contribución de sombra, ó 1.0 si no hay sombra en absoluto o no recibe sombras.
    • vec3 TO_LIGHT_DIR Vector que apunta hacia la fuente de luz.
    • vec3 NORMAL El vector normal en el espacio del mundo.
    • vec4 BASE_COLOR El color base y el valor alfa del material.
    • float METALNESS La cantidad de Metalness.
    • float ROUGHNESS La cantidad de Roughness.

    Ejemplo:

    void DIRECTIONAL_LIGHT()
    {
        DIFFUSE += LIGHT_COLOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
    }
  • void POINT_LIGHT() Cuando está presente, esta función es llamada para cada punto de luz activo en la escena para cada fragmento. La tarea de la función es añadir la contribución difusa a una variable especial escribible DIFFUSE. La función también puede elegir no hacer nada, en cuyo caso se ignoran las contribuciones difusas de las luces puntuales. Cuando la función no está presente en absoluto, las contribuciones difusas de las luces puntuales se acumulan normalmente, como lo haría un PrincipledMaterial.

    La función puede escribir en las siguientes variables especiales:

    • vec3
    • DIFFUSE Acumula las contribuciones de luz difusa, por fragmento

    . La función puede leer las siguientes variables especiales, además de los uniformes matriciales (como, MODEL_MATRIX

    )

    y vectoriales (como, CAMERA_POSITION

    )

    de la tabla anterior:

    • vec3 LIGHT_COLOR Color de luz difusa.
    • float
  • LIGHT_ATTENUATION
    • Atenuación de la luz.
    • float SHADOW_CONTRIB Contribución de sombra, o 1.0 si no hay ninguna sombra o no recibe sombras. vec3
  • TO_LIGHT_DIR
    • Vector que apunta hacia la fuente de luz.
    • vec3 NORMAL El vector normal en el espacio del mundo.
    • vec4 BASE_COLOR El color base y el valor alfa del material.
    • float METALNESS La cantidad de Metalness.
    • float ROUGHNESS La cantidad de Roughness.

    Ejemplo:

    void POINT_LIGHT()
    {
        DIFFUSE += LIGHT_COLOR * LIGHT_ATTENUATION * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
    }
  • void SPOT_LIGHT() Cuando está presente, esta función es llamada para cada foco de luz activo en la escena para cada fragmento. La tarea de la función es añadir la contribución difusa a una variable especial escribible DIFFUSE. La función también puede elegir no hacer nada, en cuyo caso las contribuciones difusas de los focos se ignoran. Cuando la función no está presente en absoluto, las contribuciones difusas de las luces puntuales se acumulan normalmente, como haría un PrincipledMaterial.

    La función puede escribir en las siguientes variables especiales:

    • vec3
    • DIFFUSE Acumula las contribuciones de luz difusa, por fragmento

    . La función puede leer las siguientes variables especiales, además de los uniformes matriciales (como, MODEL_MATRIX

    )

    y vectoriales (como, CAMERA_POSITION

    )

    de la tabla anterior:

    • vec3 LIGHT_COLOR Color de luz difusa.
    • float
  • LIGHT_ATTENUATION
    • Atenuación de la luz.
    • float SHADOW_CONTRIB Contribución de sombra, o 1.0 si no hay sombra en absoluto o no recibe sombras.
    • vec3 TO_LIGHT_DIR Vector que apunta hacia la fuente de luz.
    • float SPOT_FACTOR Factor de luz puntual.
    • vec3 NORMAL El vector normal en el espacio del mundo.
    • vec4 BASE_COLOR El color base y el valor alfa del material.
    • float METALNESS La cantidad de Metalness.
    • float ROUGHNESS La cantidad de Roughness.

    Ejemplo:

    void SPOT_LIGHT()
    {
        DIFFUSE += LIGHT_COLOR * LIGHT_ATTENUATION * SPOT_FACTOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
    }
  • void SPECULAR_LIGHT() Cuando está presente, esta función es llamada para cada luz activa en la escena para cada fragmento. La tarea de la función es añadir la contribución especular a una variable especial escribible SPECULAR. La función también puede elegir no hacer nada, en cuyo caso se ignoran las contribuciones especulares de las luces. Cuando la función no está presente en absoluto, las contribuciones especulares de las luces se acumulan normalmente, como lo haría un PrincipledMaterial.

    La función puede escribir en las siguientes variables especiales:

    • vec3 SPECULAR Acumula las contribuciones especulares de la luz, por framento.
    • Las funciones del procesador de luz normalmente le añadirán (+=
    )
    • , ya que sobreescribiendo el valor se perdería la contribución de otras luces.

    La función puede leer las siguientes variables especiales, además de los uniformes matriciales (como, MODEL_MATRIX

    )

    y vectoriales (como, CAMERA_POSITION) de la tabla anterior:

    • vec3 LIGHT_COLOR Color de luz especular.
    • float LIGHT_ATTENUATION Atenuación de luz. Para luces direccionales el valor es 1.0.
    • Para luces puntuales el valor es el mismo que LIGHT_ATTENUATION * SPOT_FACTOR de void SPOT_LIGHT()
    • .
    • float SHADOW_CONTRIB Contribución de sombra, o 1.0 si no hay sombra en absoluto o no recibe sombras. vec3
  • FRESNEL_CONTRIB
    • Contribución Fresnel del cálculo Fresnel incorporado.
    • vec3 TO_LIGHT_DIR Vector apuntando hacia la fuente de luz.
    • vec3 NORMAL El vector normal en el espacio del mundo.
    • vec4 BASE_COLOR El color base y el valor alpha del material.
    • float METALNESS La cantidad de Metalness.
    • float ROUGHNESS La cantidad de Roughness.
    • float SPECULAR_AMOUNT La cantidad especular. Este valor estará entre 0.0 y 1.0 será el mismo valor establecido en la función personalizada MAIN. Este valor será útil para calcular las contribuciones de Fresnel cuando no se utilice la contribución de Fresnel incorporada proporcionada por FRESNEL_CONTRIB
  • .
  • void SPECULAR_LIGHT()
    {
        vec3 H = normalize(VIEW_VECTOR + TO_LIGHT_DIR);
        float cosAlpha = max(0.0, dot(H, normalize(NORMAL)));
        float shine = pow(cosAlpha, exp2(15.0 * (1.0 - ROUGHNESS) + 1.0) * 0.25);
        SPECULAR += shine * LIGHT_COLOR * FRESNEL_CONTRIB * SHADOW_CONTRIB * LIGHT_ATTENUATION;
    }
  • void POST_PROCESS() Cuando está presente, esta función se llama al final de la tubería de fragmentos. La tarea de la función es finalizar COLOR_SUM con los términos difusos, especulares y emisivos finales. A diferencia de FRAGCOLOR para un material sin sombreado, COLOR_SUM será automáticamente tonemapped antes de ser escrito en el framebuffer. Para propósitos de depuración a veces es útil dar salida a un valor que no debe ser tratado como un color. Para evitar que el tonemapping distorsione este valor se puede desactivar estableciendo la propiedad tonemapMode a TonemapModeNone

    La función puede escribir en las siguientes variables especiales:

    • vec4 COLOR_SUM la salida del fragment shader.
    • El valor por defecto es vec4(DIFFUSE.rgb + SPECULAR + EMISSIVE, DIFFUSE.a)

    La función puede leer las siguientes variables especiales.

    • vec4 DIFFUSE El término difuso
    • final del fragment pipeline. vec3 SPECULAR El término especular final del fragment pipeline.
    • vec3 EMISSIVE El término emisivo final del fragment pipeline.
    • vec
    2
    • UV0 - El primer
    • conjunto de coordenadas de textura del sombreador de vértices
    • .
    • vec2 UV1 - El segundo conjunto de coordenadas de textura del sombreador de vértices.
    void POST_PROCESS()
    {
        float center_x = textureSize(SCREEN_TEXTURE, 0).x * 0.5;
        if (gl_FragCoord.x > center_x)
            COLOR_SUM = DIFFUSE;
        else
            COLOR_SUM = vec4(EMISSIVE, DIFFUSE.a);
    }
  • void IBL_PROBE() Cuando está presente, esta función es llamada para IBL (Iluminación Basada en Imágenes). La tarea de la función es añadir las contribuciones difusa y especular de IBL a las variables especiales escribibles DIFFUSE y SPECULAR

    . La función puede escribir en las siguientes variables especiales:

    • vec3 DIFFUSE Acumula las contribuciones de luz difusa, por fragmento.
    • vec3 SPECULAR Acumula las contribuciones de luz especular, por fragmento.

    La función puede leer las siguientes variables especiales.

    • vec4 BASE_COLOR El color base y el valor alfa del material.
    • float AO_FACTOR El factor de oclusión en el espacio de la pantalla.
    • float SPECULAR_AMOUNT La cantidad especular.
    • float ROUGHNESS El término emisivo final de la canalización del fragmento.
    • vec3 NORMAL El vector normal en el espacio del mundo.
    • vec3 VIEW_VECTOR Apunta hacia la cámara.
    • mat3 IBL_ORIENTATION La orientación de la sonda de luz. Proviene de SceneEnvironment::probeOrientation
  • .
  • void IBL_PROBE()
    {
        vec3 smpDir = IBL_ORIENTATION * NORMAL;
        DIFFUSE += AO_FACTOR * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, smpDir, IBL_MAXMIPMAP).rgb;
    }

Variables personalizadas entre funciones

Variables adicionales pueden ser entregadas desde la función PRINCIPAL a las otras. La palabra clave SHARED_VARS puede utilizarse para definir nuevas variables personalizadas. Se puede acceder a estas variables definidas por el usuario con SHARED.<nombre de variable>.

Por ejemplo, un material personalizado sombreado puede obtener un valor compartido en la función PRINCIPAL y utilizarlo en otras funciones.

SHARED_VARS {
    vec3 colorThreshold;
};
void MAIN()
{
    BASE_COLOR = texture(baseColorMap, UV0);
    SHARED.colorThreshold = texture(thresholdMap, UV0).rgb;
}
void DIRECTIONAL_LIGHT()
{
    if (DIFFUSE >= SHARED.colorThreshold) {
        DIFFUSE = SHARED.colorThreshold;
        return;
    }
    DIFFUSE += LIGHT_COLOR * SHADOW_CONTRIB;
}

Nota: SHARED puede ser escrito en todas las funciones sin POST_PROCESS pero es seguro escribirlo en MAIN y leerlo en las otras funciones.

Nota: Un caso de uso recomendado para escribir SHARED en funciones LIGHT es resetearlo primero en MAIN y luego acumularlo en cada función LIGHT.

SHARED_VARS {
    float sheenIntensity;
    float sheenRoughness;
    vec3 sheenColor;
    vec3 outSheenColor;
};
void MAIN()
{
    ...
    vec4 tex = texture(uSheenMap, UV0);
    SHARED.sheenColor = tex.rgb;
    SHARED.sheenIntensity = tex.a;
    SHARED.sheenRoughness = uSheenRoughness;
    SHARED.outSheenColor = vec3(0.0);
}
void SPECULAR_LIGHT()
{
    SHARED.outSheenColor += ...;
}
void POST_PROCESS()
{
    COLOR_SUM = DIFFUSE + SPECULAR + EMISSIVE + SHARED.outSheenColor;
}

Nota: MAIN se llama antes que otras, y POST_PROCESS después de todas las demás, pero no hay garantía de ningún otro orden para procesadores ligeros.

Palabras clave especiales adicionales

El código del sombreador de fragmentos personalizado puede acceder libremente a los uniformes (como, CAMERA_DIRECTION o CAMERA_POSITION), y a las variaciones pasadas desde el sombreador de vértices personalizado. Además, hay una serie de variaciones incorporadas disponibles como palabras clave especiales. Algunas de ellas son opcionales, en el sentido de que un sombreador de vértices MAIN puede calcularlas y transferirlas por sí mismo, pero para reducir la duplicación de datos, los sombreadores de fragmentos también pueden basarse en ellas. Estas funciones están disponibles en las funciones del procesador de luz y en el fragment MAIN.

  • vec3 VAR_WORLD_NORMAL - Normal interpolada transformada por NORMAL_MATRIX.
  • vec3 VAR_WORLD_TANGENT - Tangente interpolada transformada por MODEL_MATRIX.
  • vec3 VAR_WORLD_BINORMAL - Binormal interpolada transformada por MODEL_MATRIX
  • vec3 NORMAL - A diferencia de VAR_WORLD_NORMAL, que es la normal interpolada tal cual, este valor se ajusta potencialmente para la doble cara: al renderizar con el culling desactivado, la normal se invertirá según sea necesario. Por lo tanto, se recomienda utilizar NORMAL en lugar de VAR_WORLD_NORMAL para que la iluminación y otros cálculos se comporten correctamente con todos los modos de culling.
  • vec3 TANGENT - Al igual que NORMAL, este valor se ajusta potencialmente para la doble cara: cuando se renderiza con el culling desactivado, la tangente se invertirá según sea necesario.
  • vec3 BINORMAL - Al igual que NORMAL, este valor se ajusta potencialmente a la doble cara: cuando se renderiza con la función de selección desactivada, la binormal se invierte según sea necesario.
  • vec3 VAR_WORLD_POSITION - Posición interpolada del vértice en el espacio global ((MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz)
  • vec4 VAR_COLOR - El color interpolado del vértice cuando se proporcionan colores en la malla. vec4(1.0) en caso contrario.
  • vec3 VIEW_VECTOR - Apunta hacia la cámara. Se trata del vector CAMERA_POSITION - VAR_WORLD_POSITION normalizado.
  • vec4 FRAGCOORD - Contiene las coordenadas relativas a la ventana del fragmento actual.
  • float FRAMEBUFFER_Y_UP - El valor es 1 cuando el eje Y apunta hacia arriba en el sistema de coordenadas para framebuffers (texturas), lo que significa que (0, 0) es la esquina inferior izquierda. El valor es -1 cuando el eje Y apunta hacia abajo, siendo (0, 0) la esquina superior izquierda. Estas diferencias en las API gráficas subyacentes no afectan a la mayoría de los materiales personalizados. Una excepción notable es el muestreo de SCREEN_TEXTURE con coordenadas de textura no basadas en FRAGCOORD. Dado que la orientación de SCREEN_TEXTURE está ligada a la API gráfica subyacente por naturaleza, el uso de coordenadas de textura de una malla puede necesitar ajustes apropiados en la coordenada Y.

    Por ejemplo, el siguiente fragment shader, adecuado para mallas Rectangle o Cube, mostrará los objetos opacos de la escena en el modelo:

    VARYING vec2 texcoord;
    void MAIN()
    {
        vec2 screencoord = texcoord;
        if (FRAMEBUFFER_Y_UP < 0.0) // effectively: if not OpenGL
            screencoord.y = 1.0 - screencoord.y;
        BASE_COLOR = texture(SCREEN_TEXTURE, screencoord);
    }

    Cuando se muestrean texturas distintas de SCREEN_TEXTURE, y DEPTH_TEXTURE, o cuando se utiliza FRAGCOORD para calcular la coordenada de textura (que sería el caso de uso típico para acceder a las texturas de pantalla y profundidad), no es necesario realizar dicho ajuste.

  • float NDC_Y_UP - El valor es 1 cuando el eje Y apunta hacia arriba en el espacio de coordenadas normalizado del dispositivo, y -1 cuando el eje Y apunta hacia abajo. Y apuntando hacia abajo es el caso cuando el renderizado ocurre con Vulkan. La mayoría de los materiales no necesitan preocuparse por esto, pero ser capaz de bifurcarse basándose en esto puede ser útil en ciertos casos de uso avanzados.
  • float NEAR_CLIP_VALUE - El valor es -1 para cuando el rango del plano de recorte empieza en -1 y va hasta 1. Esto es así cuando se utiliza OpenGL para el renderizado. Para otros backends de renderizado el valor de esta propiedad será 0 lo que significa que el rango del plano de recorte es de 0 a 1. Este valor es útil con ciertas técnicas que involucran el DEPTH_TEXTURE

    Por ejemplo, el siguiente fragment shader demuestra una técnica para reconstruir la posición de un valor desde el buffer de profundidad para determinar la distancia desde la posición actual que se está renderizando. Cuando se utiliza en combinación con INVERSE_PROJECTION_MATRIX el valor de profundidad necesita estar en coordenadas de dispositivo normalizadas por lo que es importante asegurarse de que el rango del valor de profundidad refleja eso. Cuando NEAR_CLIP_VALUE es -1 entonces el valor de profundidad se escala para estar entre -1 y 1.

    void MAIN() {
        vec2 screen_uv = FRAGCOORD.xy / vec2(textureSize(SCREEN_TEXTURE, 0));
        float depth = texture(DEPTH_TEXTURE, screen_uv).r;
    
        if (NEAR_CLIP_VALUE < 0.0) // effectively: if opengl
            depth = depth * 2.0 - 1.0;
    
        vec4 unproject = INVERSE_PROJECTION_MATRIX * vec4(screen_uv, depth, 1.0);
        depth = (unproject.xyz / unproject.w).z;
        float viewVectorZ = (VIEW_MATRIX * vec4(VAR_WORLD_POSITION, 1.0)).z;
        depth = viewVectorZ - depth;
    
        BASE_COLOR = vec4(depth, depth, depth, 1.0);
    }
  • float IBL_EXPOSE - La cantidad de luz emitida por la sonda de luz. Proviene de SceneEnvironment::probeExposure.
    DIFFUSE += AO_FACTOR * IBL_EXPOSE * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
  • float IBL_HORIZON - El valor de corte horizontal de las reflexiones del entorno de la mitad inferior. Proviene de Horizon Cut-Off pero remapeado a [-1, 0).
    vec3 diffuse += AO_FACTOR * IBL_EXPOSE * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
    if (IBL_HORIZON > -1.0) {
        float ctr = 0.5 + 0.5 * IBL_HORIZON;
        float vertWt = smoothstep(ctr * 0.25, ctr + 0.25, NORMAL.y);
        float wtScaled = mix(1.0, vertWt, IBL_HORIZON + 1.0);
        diffuse *= wtScaled;
    }
  • float IBL_MAXMIPMAP - El nivel máximo de mipmap de IBL_TEXTURE.

Instanciación

Cuando se realiza un renderizado en instancias, algunas de las palabras clave anteriores no se aplican. Las siguientes palabras clave sólo están disponibles con instanciación:

  • INSTANCE_MODEL_MATRIX -> mat4, sustitución de MODEL_MATRIX, incluida la transformación de instanciación.
  • INSTANCE_MODELVIEWPROJECTION_MATRIX -> mat4, reemplazo de MODELVIEWPROJECTION_MATRIX, incluida la transformación de instanciación.
  • INSTANCE_COLOR -> vec4, el color de la instancia: debe combinarse con COLOR.
  • INSTANCE_DATA -> vec4, los datos personalizados de la instancia.
  • INSTANCE_INDEX -> int, el número de instancia y el índice de la tabla de instanciación.

Pantalla, profundidad y otras texturas

El pipeline de renderizado puede exponer un número de texturas a los shaders de materiales personalizados con contenido de pases de renderizado especiales. Esto se aplica tanto a los materiales personalizados sombreados como a los no sombreados.

Por ejemplo, un shader puede querer acceder a una textura de profundidad que contenga el contenido del buffer de profundidad para los objetos opacos de la escena. Esto se consigue muestreando DEPTH_TEXTURE. Tal textura no se genera normalmente, a menos que haya una necesidad real para ello. Por lo tanto, la presencia de las siguientes palabras clave en el sombreador de vértices o fragmentos también actúa como un interruptor para optar por los pases -potencialmente caros- para generar la textura en cuestión. (por supuesto, podría ser que algunas de estas ya estuvieran habilitadas debido a otros ajustes, como los parámetros de oclusión ambiental en SceneEnvironment o debido a un efecto de post-procesado que dependa de la textura de profundidad, en cuyo caso las texturas en cuestión se generan independientemente del material personalizado y por lo tanto el muestreo de estas texturas especiales en el material no tiene ningún coste adicional aparte del acceso a la textura en sí)

  • SCREEN_TEXTURE - Cuando está presente, una textura (sampler2D o sampler2DArray) con el buffer de color de un pase de renderizado que contiene el contenido de la escena excluyendo cualquier material transparente o cualquier material que también utilice el SCREEN_TEXTURE se expone al shader bajo este nombre. La textura se puede utilizar para técnicas que requieren el contenido del framebuffer en el que se están renderizando. La textura SCREEN_TEXTURE utiliza el mismo modo de borrado que View3D. El tamaño de estas texturas coincide con el tamaño de View3D en píxeles. Por ejemplo, un fragment shader podría contener lo siguiente:
    vec2 uv = FRAGCOORD.xy / vec2(textureSize(SCREEN_TEXTURE, 0));
    vec2 displace = vec2(0.1);
    vec4 c = texture(SCREEN_TEXTURE, uv + displace);

    Ten en cuenta que el uso de SCREEN_TEXTURE requiere un diseño apropiado y consciente de la escena. Los objetos que utilizan este tipo de materiales tienen que ser colocados cuidadosamente, por lo general por encima de todos los demás objetos que se espera que sean visibles en la textura. Los objetos que emplean semitransparencia de alguna forma nunca forman parte de SCREEN_TEXTURE. A menudo SCREEN_TEXTURE se utilizará en combinación con BASE_COLOR en MAIN. Por ejemplo, el siguiente sombreador de fragmentos personalizado aplica un efecto de relieve, mientras mantiene transparentes los fragmentos no tocados por objetos opacos.

    Esto supone que el objeto con el material se coloca en la parte delantera, y que tiene la mezcla activada.

    void MAIN()
    {
        vec2 size = vec2(textureSize(SCREEN_TEXTURE, 0));
        vec2 uv = FRAGCOORD.xy / size;
    
        // basic emboss effect
        vec2 d = vec2(1.0 / size.x, 1.0 / size.y);
        vec4 diff = texture(SCREEN_TEXTURE, uv + d) - texture(SCREEN_TEXTURE, uv - d);
        float c = (diff.x + diff.y + diff.z) + 0.5;
    
        float alpha = texture(SCREEN_TEXTURE, uv).a;
        BASE_COLOR = vec4(vec3(c), alpha);
    }

    Con el renderizado multivista, SCREEN_TEXTURE es una sampler2DArray. Utilice VIEW_INDEX para seleccionar la capa a utilizar. Para aplicaciones VR/AR que deseen soportar ambos tipos de renderizado, la aproximación portable es la siguiente:

    #if QSHADER_VIEW_COUNT >= 2
        vec4 c = texture(SCREEN_TEXTURE, vec3(uv, VIEW_INDEX));
    #else
        vec4 c = texture(SCREEN_TEXTURE, uv);
    #endif
  • SCREEN_MIP_TEXTURE - Idéntica a SCREEN_TEXTURE en la mayoría de los aspectos, la diferencia es que esta textura tiene mipmaps generados. Esto puede ser una característica costosa en cuanto a rendimiento, dependiendo del tamaño de la pantalla, y debido a tener que generar los mipmaps cada vez que se renderiza la escena. Por lo tanto, es preferible utilizar siempre SCREEN_TEXTURE, a menos que el material personalizado implemente una técnica que dependa de los niveles mip de la textura (por ejemplo, utilizando textureLod en el shader).
  • DEPTH_TEXTURE - Cuando está presente, una textura (sampler2D o sampler2DArray) con el contenido del búfer de profundidad (no linealizado) se expone al shader con este nombre. Sólo se incluyen los objetos opacos. Por ejemplo, un fragment shader podría contener lo siguiente:
    ivec2 dtSize = textureSize(DEPTH_TEXTURE, 0);
    vec2 dtUV = (FRAGCOORD.xy) / vec2(dtSize);
    vec4 depthSample = texture(DEPTH_TEXTURE, dtUV);
    float zNear = CAMERA_PROPERTIES.x;
    float zFar = CAMERA_PROPERTIES.y;
    float zRange = zFar - zNear;
    float z_n = 2.0 * depthSample.r - 1.0;
    float d = 2.0 * zNear * zFar / (zFar + zNear - z_n * zRange);
    d /= zFar;

    Con renderizado multivista, DEPTH_TEXTURE es un sampler2DArray. Utiliza VIEW_INDEX para seleccionar la capa a utilizar. Para aplicaciones VR/AR que deseen soportar ambos tipos de renderizado, el enfoque portable es el siguiente:

    #if QSHADER_VIEW_COUNT >= 2
        vec4 depthSample = texture(DEPTH_TEXTURE, vec3(uv, VIEW_INDEX));
    #else
        vec4 depthSample = texture(DEPTH_TEXTURE, uv);
    #endif
  • NORMAL_ROUGHNESS_TEXTURE - Cuando está presente, una textura (sampler2D) con las normales del espacio-mundo y la rugosidad del material se expone al shader bajo este nombre. Sólo se incluyen los objetos opacos. La rugosidad se almacena en el canal alfa. Por ejemplo, un sombreador de fragmentos podría contener lo siguiente:
    vec3 N = normalize(texture(NORMAL_ROUGHNESS_TEXTURE, uv).rgb);
  • AO_TEXTURE - Cuando está presente y la oclusión ambiental en el espacio de pantalla está activada (es decir, cuando la fuerza y la distancia AO son ambas distintas de cero) en SceneEnvironment, la textura SSAO (sampler2D o sampler2DArray) se expone al sombreador bajo este nombre. El muestreo de esta textura puede ser útil en materiales no sombreados. Los materiales sombreados tienen soporte de oclusión ambiental incorporado. Esto significa que el factor de oclusión ambiental se tiene en cuenta automáticamente. Mientras que en un fragment shader para un material no sombreado se podría escribir lo siguiente para lograr lo mismo:
    ivec2 aoSize = textureSize(AO_TEXTURE, 0);
    vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
    float aoFactor = texture(AO_TEXTURE, aoUV).x;

    Con el renderizado multivista, AO_TEXTURE es un sampler2DArray. Utiliza VIEW_INDEX para seleccionar la capa a utilizar. Para aplicaciones VR/AR que deseen soportar ambos tipos de renderizado, el enfoque portable es el siguiente:

    #if QSHADER_VIEW_COUNT >= 2
        ivec2 aoSize = textureSize(AO_TEXTURE, 0).xy;
        vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
        float aoFactor = texture(AO_TEXTURE, vec3(aoUV, VIEW_INDEX)).x;
    #else
        ivec2 aoSize = textureSize(AO_TEXTURE, 0);
        vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
        float aoFactor = texture(AO_TEXTURE, aoUV).x;
    #endif
  • IBL_TEXTURE - No habilitará ningún pase de renderizado especial, pero puede utilizarse cuando el material tenga Material::lightProbe o el modelo esté en el ámbito de SceneEnvironment::lightProbe.
    void IBL_PROBE()
    {
        DIFFUSE += AO_FACTOR * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
    }
  • MOTION_VECTOR_TEXTURE - Activa un pase de renderizado dedicado que calcula vectores de movimiento por objeto para la escena. La salida es una textura de cuatro canales: los componentes R y G contienen los vectores de movimiento escalados de los modelos, mientras que los componentes B y A almacenan los vectores de movimiento no escalados.
  • VIEW_INDEX - Cuando se utiliza en el código de sombreado personalizado, se trata de una variable uint (no interpolada). Cuando no se utiliza el renderizado multivista, el valor es siempre 0. Con renderizado multivista, el valor es el índice de la vista actual (por ejemplo, gl_ViewIndex). Útil en particular en combinación con DEPTH_TEXTURE y similares cuando el renderizado multivista está activado.

Véase también SceneEnvironment::tonemapMode, Uso de la iluminación basada en imágenes, Qt Quick 3D - Ejemplo de sombreadores personalizados, Qt Quick 3D - Ejemplo de materiales personalizados, y Materiales, efectos, geometría y datos de textura programables.

Documentación de propiedades

alwaysDirty : bool

Especifica que el estado del material es siempre sucio, lo que indica que el material necesita ser refrescado cada vez que es utilizado por el QtQuick3D.

destinationAlphaBlend : enumeration [since 6.7]

Especifica el factor de mezcla alfa de destino. El valor por defecto es CustomMaterial.NoBlend. Este valor sólo se utiliza activamente si sourceBlend y destinationBlend tienen un valor distinto del predeterminado.

ConstanteValor
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Nota: A efectos de compatibilidad con versiones anteriores, si se deja con su valor predeterminado, se le asignará el mismo valor que destinationBlend cuando sourceBlend y destinationBlend se establezcan en valores no predeterminados.

Esta propiedad se introdujo en Qt 6.7.

Véase también destinationBlend.

destinationBlend : enumeration

Especifica el factor de mezcla de destino. El valor por defecto es CustomMaterial.NoBlend.

ConstanteValor
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Nota: Tanto sourceBlend como destinationBlend deben tener un valor distinto del predeterminado antes de que se active la mezcla.

Véase también sourceBlend.

fragmentShader : url

Especifica el archivo con el fragmento de código del fragment shader personalizado.

El valor es una URL y debe ser un archivo local o utilizar el esquema qrc para acceder a archivos incrustados a través del sistema de recursos de Qt. También se aceptan rutas de archivo relativas (sin esquema), en cuyo caso el archivo se trata como relativo al componente (el archivo .qml ).

Advertencia: Se supone que los fragmentos de sombreado son contenido de confianza. Se recomienda a los desarrolladores de aplicaciones que consideren detenidamente las posibles implicaciones antes de permitir la carga de contenido proporcionado por el usuario que no forme parte de la aplicación.

Véase también vertexShader.

lineWidth : real

Esta propiedad determina el ancho de las líneas renderizadas, cuando la geometría está utilizando un tipo primitivo de líneas o tiras de líneas. El valor por defecto es 1.0. Esta propiedad no es relevante cuando se renderizan otros tipos de geometría, como por ejemplo, mallas triangulares.

Atención: Los anchos de línea distintos de 1 pueden no estar soportados en tiempo de ejecución, dependiendo de la API gráfica subyacente. En tal caso, se ignorará la solicitud de cambio de anchura. Por ejemplo, no es de esperar que ninguna de las siguientes API admita líneas anchas: Direct3D, Metal, OpenGL con contextos de perfil de núcleo.

Nota: A diferencia de la anchura de línea, cuyo valor forma parte del objeto de canalización gráfica, el tamaño de punto para geometrías con una topología de puntos está controlado por el sombreador de vértices (cuando es compatible) y, por tanto, no tiene una propiedad QML correspondiente.

shadingMode : enumeration

Especifica el tipo de material. El valor por defecto es Sombreado.

ConstanteValor
CustomMaterial.Unshaded
CustomMaterial.Shaded

sourceAlphaBlend : enumeration [since 6.7]

Especifica el factor de mezcla alfa fuente. El valor por defecto es CustomMaterial.NoBlend. Este valor sólo se utiliza activamente si sourceBlend y destinationBlend tienen un valor distinto del predeterminado.

ConstanteValor
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Nota: Por motivos de compatibilidad con versiones anteriores, si se deja en su valor predeterminado, se le asignará el mismo valor que sourceBlend cuando sourceBlend y destinationBlend se establezcan en valores no predeterminados.

Esta propiedad se introdujo en Qt 6.7.

Véase también sourceBlend.

sourceBlend : enumeration

Especifica el factor de mezcla de origen. El valor por defecto es CustomMaterial.NoBlend.

ConstanteValor
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Nota: Tanto sourceBlend como destinationBlend deben tener un valor distinto del predeterminado antes de que se active la mezcla.

Véase también destinationBlend.

vertexShader : url

Especifica el archivo con el fragmento de código del sombreador de vértices personalizado.

El valor es una URL y debe ser un archivo local o utilizar el esquema qrc para acceder a archivos incrustados a través del sistema de recursos de Qt. También se aceptan rutas de archivo relativas (sin esquema), en cuyo caso el archivo se trata como relativo al componente (el archivo .qml ).

Advertencia: Se supone que los fragmentos de sombreado son contenido de confianza. Se recomienda a los desarrolladores de aplicaciones que consideren detenidamente las posibles implicaciones antes de permitir la carga de contenido proporcionado por el usuario que no forme parte de la aplicación.

Véase también fragmentShader.

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