Tras añadir iluminación difusa, el siguiente paso natural es incorporar el componente especular. Nuestro tetera con textura de mármol debería verse brillante, así que empezaremos con un valor fijo y luego daremos soporte a mapas especulares, aprovechando los mapas de rugosidad incluidos en el paquete de texturas.
Comenzamos desde la entidad Material y agregamos propiedades clave: useSpecularMap para indicar si usamos un mapa, specularMap como referencia de textura de ese mapa, specularSampler como el muestreador y glossColor como el brillo constante por canal cuando no hay mapa. Igual que la textura principal, tanto specularMap como texture son referencias tipo cadena gestionadas en colecciones del motor, y textureSampler se expone para completar la configuración del material.
Convenciones y valores por defecto: cuando no usamos un mapa especular, enlazamos una textura dummy de 1x1 que mantiene el binding válido. El sampler principal lo renombramos a default porque bilinear en UVs funciona bien para la mayoría de casos. La textura dummy se crea en GPU con formato rgba8unorm y un único texel blanco, escrita con writeTexture, y así el pipeline no cambia su configuración al alternar entre mapa y constante.
Inicialización de materiales de ejemplo: para mármol empleamos la textura marble con useSpecularMap desactivado y un glossColor alto como 4 4 4 1 para un brillo marcado. Para una tela roja, usamos red-fabric sin componente especular constante o con valores bajos, ya que es un material mate. Más adelante podemos activar useSpecularMap y apuntar a marble-roughness o red-fabric-roughness para experimentar con mapas reales.
Vinculaciones de material en el render pass: la función que antes configuraba la textura principal ahora se convierte en setMainMaterialBindGroup y recibe sampler y textura del material, además de un buffer uniforme con useSpecularMap y glossColor. Se añaden también el sampler y la vista del mapa especular. Importante no olvidar crear la vista de la textura con createView antes de enlazarla, ya que WebGPU arroja un mensaje de error confuso si se omite. También es necesario que estos recursos se usen realmente en el shader, de lo contrario el compilador podría eliminarlos.
Mapas especulares como mapas de rugosidad: en nuestro flujo de trabajo los mapas son de rugosidad, por lo que se invierten para obtener brillo. Rugosidad 0 implica superficie muy brillante y 1 implica totalmente difusa. Aunque las imágenes actuales son en blanco y negro, nuestro pipeline calcula especular por canal, de modo que más adelante podremos admitir variaciones por canal sin cambiar la arquitectura.
Lógica del shader sin ramas: en fragmento, primero muestreamos el mapa de rugosidad y calculamos brillo como 1 menos rugosidad. Luego combinamos con el brillo constante usando mix entre el valor del mapa y glossColor en función de useSpecularMap. Esta mezcla evita ramificaciones y mantiene el shader eficiente. Para la luz especular usamos el modelo tipo Blinn Phong con half vector entre dirección a luz y a cámara, elevando la contribución por canal con el exponente de brillo. Si algún canal del brillo es cero, se anula la especular en ese canal. El color final se obtiene multiplicando el albedo por la suma de difusa y especular.
Resultados y ajuste: funciona, pero la escala entre rugosidad y el exponente de brillo no mapea de manera física perfecta, por lo que el aspecto puede quedar sub o sobreexpuesto. Podemos introducir factores de escalado o dar el salto a un modelo PBR completo cuando sea oportuno. Mientras tanto, usar constantes claras para materiales como mármol y bajas para telas ofrece un resultado convincente y predecible.
Valores prácticos de partida: mármol con gloss 4 4 4 1 y tela con gloss 0 0 0 1. Conmutar entre usar mapa o constante permite comparar rápidamente y elegir el enfoque adecuado por material.
Código de referencia del capítulo: versión 0.5 del repositorio
Acerca de Q2BSTUDIO: somos una empresa de desarrollo de software que crea aplicaciones a medida y software a medida con foco en calidad, rendimiento y escalabilidad. Integramos inteligencia artificial e ia para empresas, implantamos servicios cloud aws y azure, reforzamos ciberseguridad y pentesting, y potenciamos decisiones con servicios inteligencia de negocio y power bi. Si quieres construir un motor gráfico, una plataforma 3D o cualquier solución compleja de extremo a extremo, te ayudamos a llevarla de la idea a producción.
Te invitamos a conocer cómo abordamos proyectos de alto rendimiento y arquitecturas modernas en nuestro servicio de aplicaciones a medida y software a medida, y cómo desplegarlos y operarlos con fiabilidad en servicios cloud aws y azure. También trabajamos con agentes IA, automatización y analítica avanzada para que tus productos crezcan de forma sostenible y segura.
Palabras clave para encontrar este contenido: aplicaciones a medida, software a medida, inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio, ia para empresas, agentes IA, power bi.