Guía para programacion de shaders con HLSL en UE5 / Unity
Guía para programación de shaders en HLSL con UE5 / Unity3D
Imagen usada solo como referencia - Midjourney
Que es un shader?
Un proceso de calculo linear, que permite ejecutar
tareas generativas para componentes visuales, modelando
los procesos de renderización para cada pieza de hardware.
Shaders
Los shaders en plataformas como Unity 3D están construidos sobre un sistema llamado “ShaderLab” con el que se personalizan y modifican las opciones de uso, en cambio en plataformas como Unreal Engine solo están disponibles por medio de compilación directa con las variables globales definidas en los entornos CS / GL / HLSL , los sistemas de pre-compilado integrados en algunas plataformas de producción, funcionan con nodos gráficos ó con capas de shaders pre-establecidas para el entorno.
HLSL
Es un lenguaje de tipádo estático, esto significa que cada variable tiene un valor específico explícitamente definido que no puede ser modificado, las siguientes tablas pueden ser utilizadas para escribir en cualquier tipo de motor que incluya, compatibilidad con HLSL (High Level Shading Language) / OpenGL.
La semantica soportada en DIRECT3D9 y 10:
Variable | Descripción | Tipo |
---|---|---|
BINORMAL[n] | Binormal | float4 |
BLENDINDICES[n] | Blend indices | uint |
BLENDWEIGHT[n] | Blend weights | float |
COLOR[n] | Diffuse/specu | float4 |
NORMAL[n] | Normal vector | float4 |
POSITION[n] | Posición vértice | float4 |
POSITIONT | Posición trans | float4 |
PSIZE[n] | Tamaño punto | float |
TANGENT[n] | Tangente | float4 |
TEXCOORD[n] | Coord texturas | float4 |
FOG | Niebla vértice | float |
TESSFACTOR[n] | Factor tesela | float |
VFACE | Cara +/- | float |
VPOS | Locación pixel | float2 |
DEPTH[n] | Profundidad | float |
La semántica par DIRECT3D 10 y posteriores es la siguiente:
Variable | Descripción | Tipo |
---|---|---|
SV_ClipDistance[n] | Distancia de datos de el clip. | float |
SV_CullDistance[n] | Distancia de datos de el cull. | float |
SV_Coverage | Una mascara que puede ser especificada en la linea de entrada o salida del pixel. | uint |
SV_Depth | Buffer de datos de profundidad. | float |
SV_DepthGreaterEqual[n] | Prueba si el valor es mayor ó igual a la profundidad de datos. | unknow |
SV_DepthLessEqual[n] | Prueba si el valor es menor ó igual a la profundidad de datos. | unknow |
SV_DispatchThreadID | Define un hilo global dentro del llamado del despachador (solo lectura) por dimension de el grupo. | uint3 |
SV_DomainLocation | Define la locación del dominio actual. | float2/3 |
SV_GroupID | Define el grupo con el llamado del identificador. | uint3 |
SV_GroupIndex | Provee un indice plano al hilo del grupo definido. | uint |
SV_GroupThreadID | Define el identificador del hilo, según la dimension. | uint3 |
SV_GSInstanceID | Define la instancia del shader geométrico. | uint |
SV_InnerCoverage | Representa datos subestimados de la información de rasterización. | unknow |
SV_InsideTessFactor | Define el monto de teselación sobre la superficie del parche definido sobre el dominio del shader para ser leído. | float/float2 |
SV_InstanceID | Identificador por instancias automáticamente generadas por el runtime (ver tabla de valores generados por el sistema). | unknow |
SV_IsFrontFace | Especifica si un triangulo esta de frente, para lineas y puntos. | bool |
SV_OutputControlPointID | Define un indice de el ID según el punto de control siendo operada por un punto de invocación principal. | uint |
SV_Position | Cuando se declara para ingreso de un shader pude tener dos modos de interpolación *linearNoperspective *linearNoPerspectiveCentroid | float4 |
SV_PrimitiveID | Identificador primitivo automático generado por el runtime. | uint |
SV_RenderTargetArrayindex | Genera un render de el indice array objetivo, aplicado a la geometría de la salida del shader e indica el slice del array del render objetivo que el primitivo dibujara en el shader del pixel. | uint |
SV_SampleIndex | Muestra el indice de frecuencia de datos (Pixel shader solo). | uint |
SV_StencilRef | Representa valor de referencia del shader por pixel (Pixel shader solo). | uint |
SV_Target[n] | El valor de salida guardado where 0 >= n <=7 en el render objetivo, el indice muestra cual de las 8 opciones es condicional al render solicitado para escribirlo. | float |
SV_TessFactor | Define el monto de teselación en cada borde de el parche disponible para escribir en el dominio del shader. | float[2/3/4] |
SV_VertexID | Define el identificador por vertex automáticamente generado por el runtime | uint |
SV_ViewportArrayindex | Vista de indice de array, aplicado a la salida de la geometría del shader, indica cual vista sera usada por el primitivo actualmente para ser escrita. | uint |
Las declaraciones de flujo de control habilitadas son:
- continue
- discard
- do
- for
- if
- switch
- while
La tabla de valores generados por el sistema son los siguientes:
- VertexID => Identificador de vértice utilizado por cada shader (Si el identificador del vértice sobrepasa [2lexp32(-1)], lo define como 0).
- PrimitiveID => Identificativo de primitiva.
- InstanceID => Instancia de geometría.
Snippets HLSL
Los snippets se ubican en medio de los argumentos CGPROGRAM - ENDCG (GLPROGRAM - ENDGL), o podemos utilizar la alternativa HLSLPROGRAM - ENDHLSL si no vamos a incluir el soporte automatico HLSL junto con las variables globales de shader, todos los snippets comienzan con la declaración #pragma junto la directiva indicando cual función de shader para compilar:
-#pragma vertex <nombre> => Compila la funcion <nombre>
como el shader vertex.
-#pragma fragment <nombre> => Compila la funcion <nombre>
como el shader fragment.
-#pragma geometry <nombre> => Compila la funcion <nombre>
como un DX11 shader de geometria,
esta declaracion automaticamente
habilita #pragma target 4.0.
-#pragma hull <nombre> => Compila la funcion <nombre> como
un DX11 shader hull, esta
declaracion automaticamente
habilita #pragma target 5.0 .
-#pragma domain <nombre>=>Compila la funcion <nombre>
como un DX11 shader de dominio,
esta declaracion automaticamente
habilita #pragma target 5.0 .
Otras directivas de compilacion:
-#pragma target <nombre> => Shader objetivo a compilar.
-#pragma require <directiva>=>Controlador graneado en
el cual las prestaciones del GPU se
presentan aordes a la nesecidad del shader.
-#pragma only_renderers <nombres en espacios separados> =>
Compilar shader solo para los renderizadores
dados, por defecto los shaders son compilados
por todos los renderizadores.
-#pragma exclude_renderers <nombre en espacios separados> =>
No compila el shader para los renderizadores
dados.
-#pragma multi_compile ... => Para trabajar con multiples
variantes de shader.
-#pragma enable_d3d11_debug_symbols=>Genera informacion
con debug para los shaders compilados
en DirectX11, esto te permite realizar
un debuging con la herramienta debugger
grafico en visual studio.
-#pragma hardware_tier_variants <nombre de renderizado> =>
Genera un shader de hardware con multiples
variantes para cada shader compilado.
Plataformas de renderizadores:
- d3d11
- glcore
- gles
- gles3
- metal
- vulkan
- d3d11_9x
- xboxon e
- ps4
- psp2
- n3ds
- wiiu
Ejemplo de uso
#pragma only_renderers vulkan
Escribir un programa de multiples variantes de shader
La sintaxis de uso es similar a:
pragma multi_compile
Este ejemplo compila multiples variantes de shader:
-multi_compile_fwdbase => Compila todas las variantes
necesitadas por <ForwardBase>.
-multi_compile_fwdadd => Compila todas las variantes
nesecitadas por <ForwardAdd>.
-multi_compile_fwdadd_fullshadows => Compila las
variantes nesecitadas por
<ForwardAdd>, adicionalmente
incluye la habilidad para las
luces de tener sombras en
tiempo real.
-multi_compile_fog => Expande a algunas variantes
el manejo de diferentes tipos
de niebla <off/linear/exp/exp2>
Shader “nombre” { [Properties] Subshaders [Fallback] [CustomEditor] }
Los tipos de valor acordes a la precisión que se requieran de la variable, esto se ve reflejado en el desempeño y consumo de recursos.
+ INT(Valores enteros/Usualmente las GPU de 3th generación en adelante
procesan todos los valores, con este tipo de variable declarativa, la diferencia
y utilidad se ve en dispositivos móviles).
+ FIXED(Valores fijados entre -2 y 2).
+ HALF(Valores de baja precision 2 dígitos).
+ FLOAT(Valores de alta precision 3 dígitos).
Los tipos de vector pueden ser de acuerdo a la cantidad que se vayan a utilizar el monto máximo es 4 vectores por tipo, por ejemplo:
+ FIXED4 COLOR = FIXED4(1,0.6,0.7,1);
+ FLOAT3 POS = FLOAT3(1,1,1);
+ FLOAT2 TEXCORD = FLOAT2(0.5,0.5);
Adicional a estos se encuentran los tipos de vector matrix, que son un vector de una serie de vectores, sin generar una instancia de el conjunto de vectores.
- FLOAT4X4
- FLOAT2X2
Cuando se utiliza para multiplicación de matrix deben usarse vectores de 4 puntos.
- FLOAT4
Los samplers son usados para leer texturas 2d o 3d:
- SAMPLER2D
- SAMPLER3D
Finalmente los structs, tipos de datos personalizados que pueden almacenar otros tipos de datos.
Struct + $Nombre-de-conjunto + {FLOAT4 var; FIXED4 var; HALF4 var}
La sintaxis para el tipo de shader siempre constara de la siguiente declaracion:
Shader + $Nombre-de-shader + {Subshader{Pass{Tags{ }}}
La comunicación con el shader debe ser mencionada en CGPROGRAM-ENDCG respectivamente:
Shader "<nombre_shader>"{
Subshader{
Pass{
Tags{"RenderType"="" "Queue"=""}
GrabPass{"nombre textura"}
CGPROGRAM
#include "<la ubicación y nombre de tu archivo>.cginc || .glslinc"
***Agregaremos el struct de ingreso de datos
struct in{
***Declaramos el tipo de variable según la cantidad de vectores 2,3,4
fixed x : y;
half z : w;
float a : b;
}
***Ahora el struct de subshader
struct v2f{
***Agrega el contenido de variabilidad.
}
ENDCG
}
}
}
Shaders en Unity3D
ShaderLab
Una clase de shaders principales, los cuales se utilizan para
anidar otros shaders, un sistema de instancia concurrente
para el uso de variables globales en un entorno local.
Shaders integrados en U3D:
- HSLSSupport.cginc Automáticamente incluido.
- UnityShaderVariables.cginc Automáticamente incluido, variables globales comunes.
- UnityCG.cginc Son una serie de funciones que incluye Unity 3D para escribir shaders de manera simple.
Funciones de transformación de vértice:
float4 UnityObjectToClipPos(float3 pos) Transforma un punto desde el espacio del objeto el espacio de la cámara en coordenadas homogéneas, esto es equivalente a
(mul(UNITY_MATRIX_MVP,float4(pos, 1.0)))
float3 UnityObjectToViewPos(float3 pos) Transforma un punto desde un objeto del espacio para la vista del espacio, esto es equivalente a:
mul(UNITY_MATRIX_MV,float4(pos, 1.0)).xyz
Funciones genéricas ayudantes:
Retorna la dirección en el espacio del mundo desde la posición del vértice en el espacio del objeto hacia la cámara.
float3 WorldSpaceViewDir(float4 v)
Retorna la dirección en el espacio del objeto desde la posición del vértice en el espacio del objeto hacia la cámara.
float3 ObjSpaceViewDir(float4 v)
Calcula la compensación de UV para mapeado de normal en parallax.
float2 ParallaxOffset(half h, half height, half3 viewDir)
Convierte el color a iluminación (escala de grises).
fixed Luminance(fixed3 c)
Decodifica el color desde el mapa de iluminación (Ligthmap) (RGBM o dLDR según la plataforma).
fixed3 DecodeLightmap(fixed4 color)
Codifica un valor flotante de rango en un color RGBA, para almacenar en render de baja precision.
float4 EncodeFloatRGBA(float v)
Decodifica un color RGBA a un valor flotante.
float DecodeFloatRGBA(float4 enc)
Codifica un rango de valor flotante en un float2.
float2 EncodeFloatRG(float v)
Decodifica un valor RG flotante previamente codificado.
float DecodeFloatRG(float2 enc)
Codifica una vista de la normal en espacio dentro de un rango de dos valores.
float2 EncodeViewNormalStereo(float3 n)
Decodifica la vista de la normal en el espacio desde enc4.xyz.
float3 DecodeViewNormalStereo(float4 enc4)
Funciones de renderizado (Forward):
Computa la dirección según el espacio del mundo hacia la luz dando una posición de vértice en el espacio del objeto.
float3 WorldSpaceLightDir(float4 v)
Computa la dirección según el espacio del objeto hacia la luz dando una posición de vértice en el espacio del objeto.
float3 ObjSpaceLightDir(float4 v)
Computa iluminación desde cuatro puntos de luz, con datos de luz empacadas en vectores, el render Forward usa esto para iluminación por vértice.
float3 Shade4PointLights
Funciones para espacio de pantalla ayudantes:
Computa las coordenadas de la textura para realizar un mapeado la muestra de textura, el ingreso es un clip con la posición espacial.
float4 ComputeScreenPos(float4 clipPos)
Computa las coordenadas de la textura para samplear una textura (GrabPass).
float4 ShadeVertexLights(float4)
GrabPass{ } => Es un pase especial de renderizado, toma una muestra
del contenido de la pantalla donde el objeto se encuentra para ser
dibujado hacia una textura.
Funciones para renderizado(Vertex-lit):
Computa la iluminación desde cuatro luces por vértice y ambiente, dando al objeto posición según el espacio relacional y normales.
float3 ShadeVertexLights(float4 vertex, float3 normal)
Prepara el shader
Escribir un shader que interactúe con la luz es complejo, estos tienen diferentes tipos de luz, diferentes opciones de sombreado y rutas de render, el código generado por Unity en este sentido es para estructurar una clase typo SurfaceShader que es propia del entorno.
La estructura de salida por defecto es:
struct SurfaceOutputSpecular{
fixed3 Albedo; => Color difuso
fixed3 Specular; => Color especular
fixed3 Normal; => Normal de la tangente espacial
fixed3 Emission; => Emisión
half Smoothness; => Suavizado
half Occlusion; => Oclusión
fixed Gloss; => Intensidad del especular
fixed Alpha; => Alfa por transparencias
};
struct SurfaceOutputStandard{
fixed3 Albedo;
fixed3 Normal;
half3 Emission;
half Metallic;
half Smoothness;
half Occlusion;
fixed Alpha;
};
Directivos de compilación de SurfaceShader, la semántica es:
pragma surface surfaceFunction lightModel [optionalparams]
parámetros requeridos:
surfaceFunction => Debe incluir un tipo de función en la forma:
---<void surf(Input IN, inout SurfaceOutput o)>
Donde Input es una estructura previamente definida,
debe contener las coordenadas de texturas
y variables automáticas adicionales necesarias
para la función del shader superficial.
lightModel => Modelo de luz a ser utilizado, no físicos como Standard y StandardSpecular, asi como no físicos, Lambert(Difuso) y BlinnPhong(Especular).
---Standard => Este modelo de iluminación utiliza
la salida struct SurfaceOutputStandard.
---StandardSpecular => Este modelo de iluminación
utiliza la salida struct SurfaceOutputStandardSpecular.
---Lambert => No es un modelo físico.
---BlinnPhong => No es un modelo físico.
---Custom => Componente modelo de iluminación
personalizado.
optionalparams:
---alpha || alpha:auto => Escoge valores por defecto
para el tratamiento del canal de transparencia.
---alpha:blend => Habilita la mezcla del canal de
transparencia.
---alpha:fade => Habilita el difuminado-transparencia.
---alpha:premul => Habilita el modo pre-multiplicado al
canal de difuminado-transparencia.
---alpha:VariableName => Habilita el modo de cierre de
transparencia al canal de transparencia,
este valor es un flotante con <VariableName>,
puede usarse en conjunto con la directiva
<addshadow> para generar un pase de sombra apropiado.
---keepalpha => Por defecto el surface shader estará
escrito en un nivel opaco (1.0) a un canal alpha.
---decal:add => Shader aditivo, esto es cuando un
objeto reposa sobre la superficie de otros
elementos usando una mezcla aditiva.
---decal:blend => Shader semitransparente.
Funciones modificadores:
---vertex:VertexFunction => Función de modificación de
vértice personalizada.
---finalcolor:ColorFunction => Función de modificación
de color final.
---finalgbuffer:ColorFunction => Ruta personalizada
diferida para el contenido alternado de gbuffer.
---finalprepass:ColorFunction => Ruta personalizada
para el pre-pase base.
Sombras y teselación:
---addshadow => Genera un pase caster de sombra.
---fullforwardshadow=>Soporte para todo tipo de
sombras en rutas de render forward,
soporta todas las luces en el escenario.
---tessellate:TessFunction=>Uso de teselación
GPU DX11, la función computa los
factores de teselación.
Opciones de generación de código:
---exclude_path:deferred => Excluye el tipo de pase.
---exclude_path:forward => Excluye el tipo de pase.
---exclude_path:prepass => Excluye el tipo de pase.
---noshadow => Deshabilita todas las sombras
soportadas por el shader.
---noambient => Deshabilita las luces de ambiente.
---novertexlights => Deshabilita la iluminación
por vertex.
---nolightmap => Deshabilita el mapa de iluminación
en este shader.
---nodynlightmap => Deshabilita el soporte a la
iluminación global dinámica.
---nodirlightmap => Deshabilita el soporte al mapa
de luz direccional.
---nofog => Deshabilita el soporte que trae por
defecto de niebla.
---nometa => Deshabilita el generar un pase meta.
---noforwardadd => Deshabilita el soporte al
renderizado forward junto con el render
adicional del pase.
---nolppv => Deshabilita el soporte a Light Probe
Proxy Volume un componente que permite utilizar
mas información de iluminación para largos y
dinámicos Game Objects, partículas o mesh en general.
---noshadowmask => Deshabilita el soporte a la mascara
de sombra para este shader.
Opciones miscelaneas:
---softvegetation => Forzara al Surface shader a solo
ser renderizado cuando soft-vegetation este en
funcionamiento.
---interpolateview => Computar dirección de vista
en el vertice del shader e interpolarlo.
---halfasview => Realiza un pase vector de direccion
media dentro de la funcion de iluminacion en lugar
de la direccion de la vista.
---dualforward => Habilita el uso de mapas de iluminacion
duales en la ruta de renderizado forward.
---dithercrossfade => Habilita el soporte a efectos
de dithering en el surface shader, puedes aplicar
este shader a un GO que utiliza un componente LOD group.
Estructura de Input para Surface Shader
La estructura del input generalmente incluye una coordenada de textura necesaria para el shader, las coordenadas de la textura debe ser llamada “uv” seguido del nombre de la textura en caso de utilizar mas de una textura la semantica seria ( uv[n] ).
---float3 viewDir => Contiene la direccion de vista
para computar efectos de parallax,
iluminacion rim, etc.
---float4 COLOR => Contiene un color por vertice incorporado.
---float4 screenPos => Contiene la posicion de la pantalla
segun el espacio para efectos de reflexion
o camara en espacio, no compatible con
GrabPass, para GrabPass debes computar
tus UV con ComputeGrabScreenPos.
---float3 worldPos => Contiene la posicion del espacio global.
---float3 worldRefl => Contiene el vector de reflexion del
espacio global.
---float3 worldNormal => Contiene el vector de normal del
espacio global.
---float3 worldrefl; INTERNAL_DATA => Contiene el vector de
reflexion segun el espacio global, para
obtener el vector de reflexion basado en
un mapa de normal por pixel, utiliza
WorldReflectionVector(IN, o.Normal)
---float3 worldNormal; INTERNAL_DATA => Contiene el vector de
normal segun el espacio global, para
obtener el vector de normal basado en
un mapa de normal por pixel, utiliza
WorldNormalVector(IN, o.Normal)
Variantes de hardware en shaders:
-#pragma hardware_tier_variants <rederizador>
-UNITY_HARDWARE_TIER1
-UNITY_HARDWARE_TIER2
-UNITY_HARDWARE_TIER3
Shaders en Unreal Engine 4/5
HLSL se puede utilizar a través de diferentes métodos en UE, scripts anidados dentro de un material compositivo que se pueden reutilizar durante la etapa de desarrollo en diferentes escenarios,nodos personalizados con diferentes entradas de los componentes de Blueprint, lo que le permite mezclar e integrar fácilmente un nuevo shader al proyecto.
Shader globalizado
Una técnica común para ampliar el conjunto actual de shaders disponibles en el motor es mediante la adición de nuevos en los mismos espacios, /Engine/Shaders o en la ruta /Plugins/Shaders, cada diseño de sistema tiene sus propios pros/contras y casos de uso, si está buscando tener un nuevo conjunto de materiales de shader que se puedan usar en cualquier lugar, deben agregarse directamente al espacio de nombres del motor; eventualmente, puede crear otros complementos basados en estos shaders globalizados o incluso puede limitar los shaders que se utilizarán directamente en un complemento.
Nodo blueprint personalizado
Actúa como un puente entre los archivos externos y el editor para conectar USF/USH/HLSL con el material, siempre puedes escribir directamente dentro del nodo personalizado en caso de que no vaya a ser usado externamente, los tipos de expresión básicos que se traducen directamente a tipos de expresión HLSL están expuestos para su uso en archivos USH/USF desde los nodos personalizados dentro del material,su sintaxis es similar a C, por lo que se puede ampliar, anidar y reutilizar para diferentes casos.
HLSL material expresions para UE
Traductor de materiales
El traductor de materiales tiene solo un par de métodos disponibles desde la API pública, pero si necesita trabajar con el píxel buffer directamente, es mejor extender la clase con alguna versión personalizada del traductor, pero el buffer de vértices e índices es accesible desde los recursos de renderizado del objeto.
int32 GetNumUserTexCoords() const;
int32 GetNumUserVertexTexCoords() const;
void ClearAllFunctionStacks();
void ClearFunctionStack(uint32 Frequency);
void AssignTempScope(TArray<FShaderCodeChunk>& InScope);
void AssignShaderFrequencyScope(EShaderFrequency InShaderFrequency);
void GatherCustomVertexInterpolators(TArray<UMaterialExpression*> Expressions);
void CompileCustomOutputs(TArray<UMaterialExpressionCustomOutput*>& CustomOutputExpressions, TSet<UClass*>& SeenCustomOutputExpressionsClasses, bool bIsBeforeAttributes);
EMaterialExpressionVisitResult VisitExpressionsRecursive(TArray<UMaterialExpression*> Expressions, IMaterialExpressionVisitor& InVisitor);
EMaterialExpressionVisitResult VisitExpressionsForProperty(EMaterialProperty InProperty, IMaterialExpressionVisitor& InVisitor);
void ValidateVtPropertyLimits();
void ValidateShadingModelsForFeatureLevel(const FMaterialShadingModelField& ShadingModels);
bool Translate();
void GetMaterialEnvironment(EShaderPlatform InPlatform, FShaderCompilerEnvironment& OutEnvironment);
// Assign custom interpolators to slots, packing them as much as possible in unused slots.
TBitArray<> GetVertexInterpolatorsOffsets(FString& VertexInterpolatorsOffsetsDefinitionCode) const;
void GetSharedInputsMaterialCode(FString& PixelMembersDeclaration, FString& NormalAssignment, FString& PixelMembersInitializationEpilog);
FString GetMaterialShaderCode();
Vector / float
float/2/3/4 se puede interpretar como un retorno vectorial para el nodo personalizado o puede usar MaterialAttributes para definir parámetros adicionales o devolver múltiples salidas con múltiples entradas también, la ruta de renderizado se puede cambiar y definir a través de la capa de paso del propio shader, si desea especificar un archivo HLSL directamente puede ser posible y se interpretará automáticamente desde el nodo personalizado con un simple include, no olvide asignar el directorio de shaders con la siguiente función ´AddShaderSourceDirectoryMapping´ una vez que haya agregado el módulo ´RenderCore´ en el archivo de compilación del proyecto.
/** Usado para obetener un tipo "amigable" desde EMaterialValueType */
const TCHAR* FHLSLMaterialTranslator::DescribeType(EMaterialValueType Type) const
{
switch(Type)
{
case MCT_Float1: return TEXT("float");
case MCT_Float2: return TEXT("float2");
case MCT_Float3: return TEXT("float3");
case MCT_Float4: return TEXT("float4");
case MCT_Float: return TEXT("float");
case MCT_Texture2D: return TEXT("texture2D");
case MCT_TextureCube: return TEXT("textureCube");
case MCT_Texture2DArray: return TEXT("texture2DArray");
case MCT_VolumeTexture: return TEXT("volumeTexture");
case MCT_StaticBool: return TEXT("static bool");
case MCT_MaterialAttributes: return TEXT("MaterialAttributes");
case MCT_TextureExternal: return TEXT("TextureExternal");
case MCT_TextureVirtual: return TEXT("TextureVirtual");
case MCT_VTPageTableResult: return TEXT("VTPageTableResult");
case MCT_ShadingModel: return TEXT("ShadingModel");
default: return TEXT("unknown");
};
}
EMaterialValueType
Traducción del tipo de valor del material, en caso de que desee mezclar diferentes tipos de salidas para evaluar el tipo de material.
/** Usado para obtener un tipo HLSL desde EMaterialValueType */
const TCHAR* FHLSLMaterialTranslator::HLSLTypeString(EMaterialValueType Type) const
{
switch(Type)
{
case MCT_Float1: return TEXT("MaterialFloat");
case MCT_Float2: return TEXT("MaterialFloat2");
case MCT_Float3: return TEXT("MaterialFloat3");
case MCT_Float4: return TEXT("MaterialFloat4");
case MCT_Float: return TEXT("MaterialFloat");
case MCT_Texture2D: return TEXT("texture2D");
case MCT_TextureCube: return TEXT("textureCube");
case MCT_Texture2DArray: return TEXT("texture2DArray");
case MCT_VolumeTexture: return TEXT("volumeTexture");
case MCT_StaticBool: return TEXT("static bool");
case MCT_MaterialAttributes: return TEXT("FMaterialAttributes");
case MCT_TextureExternal: return TEXT("TextureExternal");
case MCT_TextureVirtual: return TEXT("TextureVirtual");
case MCT_VTPageTableResult: return TEXT("VTPageTableResult");
case MCT_ShadingModel: return TEXT("uint");
default: return TEXT("unknown");
};
}
Fábrica de vertex
Transformación de búfer de píxeles y vértices a través de Vertex Factory, completamente diseñada para Unreal Engine, también multiplataforma y compatible con cualquier RHI, pero tenga cuidado porque la implementación podría diferir en algunos aspectos menores, UE proporciona un nuevo nodo personalizado que puede permitirle simplificar el proceso de la migración para otras plataformas, básicamente incluye la referencia de los archivos USF/USH en un nodo gráfico al que se puede acceder a través del BP (Blueprint), eventualmente la interpretación para cada plataforma depende del RHI objetivo, cada material contiene una versión interpretada del tipo para UE de esta manera puede replicar múltiples shaders en el editor basados en estos parentales externos, una vez que el nodo gráfico basado en la interfaz toma como referencia el archivo externo, puede escribir uno nuevo, agregando los datos del externo, con los cambios proporcionados por el lado de BP para tener una versión final con ambos contextos, cualquier material instanciado basado en el shader generado puede eventualmente tipificarse en múltiples tipos nuevos según el caso de uso, evitando permutaciones innecesarias.
Si un pase en particular no recibe suficiente información, el marco genera la parte faltante con el estándar requerido, pero depende del contexto, esta segunda versión del shader generada desde el editor incluye código adicional necesario para satisfacer los parámetros solicitados, que es parte del del codigo reflejo, código de sección incluido como estándar para cada nuevo tipo derivado de UE, es por eso que puede reconocerse como parte de un nuevo módulo, en esencia todo son módulos que se pueden utilizar libremente según los desafíos que presente el proyecto.
Los componentes encontrados en el lenguaje, nos permiten desarrollar nuevas secuencias de producción, para optimizar la calidad y desempeño de nuestro contenido gráfico en dispositivos compatibles con OpenGL / HLSL / CG, la depuración de perfil en el rendimiento es factor primordial, para preservar la estabilidad-calidad del aplicativo, aboliendo el consumo de recursos en segundo plano, debemos considerar el tipo de hardware para hacerlo optimo segun las especificaciones de uso definidas por el servicio.
Referencias y mayor información puede ser encontrada en los siguientes enlaces