import { Extension , GLTF , ReaderContext , WriterContext , vec3 } from '@gltf-transform/core' ; import { KHR_MATERIALS_SHEEN } from '../constants' ; import { Sheen } from './sheen' ; const NAME = KHR_MATERIALS_SHEEN ; interface SheenDef { sheenColorFactor ? : vec3 ; sheenRoughnessFactor ? : number ; sheenColorTexture ? : GLTF . ITextureInfo ; sheenRoughnessTexture ? : GLTF . ITextureInfo ; } /**
 * # MaterialsSheen
 *
 * [`KHR_materials_sheen`](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_sheen/)
 * defines a velvet-like sheen layered on a glTF PBR material.
 *
 * ![Illustration](/media/extensions/khr-materials-sheen.png)
 *
 * > _**Figure:** A cushion, showing high material roughness and low sheen roughness. Soft
 * > highlights at edges of the material show backscattering from microfibers. Source: Khronos
 * > Group._
 *
 * A sheen layer is a common technique used in Physically-Based Rendering to represent
 * cloth and fabric materials.
 *
 * Properties:
 * -  Sheen *
 * ### Example
 *
 * The `MaterialsSheen` class provides a single  ExtensionProperty type, `Sheen`,
 * which may be attached to any  Material instance. For example:
 *
 * ```typescript
 * import { MaterialsSheen, Sheen } from '@gltf-transform/extensions';
 *
 * // Create an Extension attached to the Document.
 * const sheenExtension = document.createExtension(MaterialsSheen);
 *
 * // Create a Sheen property.
 * const sheen = sheenExtension.createSheen()
 * 	.setSheenColorFactor([1.0, 1.0, 1.0]);
 *
 * // Attach the property to a Material.
 * material.setExtension('KHR_materials_sheen', sheen);
 * ```
  export class MaterialsSheen extends Extension { public readonly extensionName = NAME ; public static readonly EXTENSION_NAME = NAME ; /** Creates a new Sheen property for use on a  Material .  public createSheen ( ) { return new Sheen ( this . document . getGraph ( ) ) ; } hidden public read ( context ) { const jsonDoc = context . jsonDoc ; const materialDefs = jsonDoc . json . materials || [ ] ; const textureDefs = jsonDoc . json . textures || [ ] ; materialDefs . forEach ( ( materialDef , materialIndex ) => { if ( materialDef . extensions && materialDef . extensions [ NAME ] ) { const sheen = this . createSheen ( ) ; context . materials [ materialIndex ] . setExtension ( NAME , sheen ) ; const sheenDef = materialDef . extensions [ NAME ] as SheenDef ; if ( sheenDef . sheenColorFactor !== undefined ) { sheen . setSheenColorFactor ( sheenDef . sheenColorFactor ) ; } if ( sheenDef . sheenRoughnessFactor !== undefined ) { sheen . setSheenRoughnessFactor ( sheenDef . sheenRoughnessFactor ) ; } if ( sheenDef . sheenColorTexture !== undefined ) { const textureInfoDef = sheenDef . sheenColorTexture ; const texture = context . textures [ textureDefs [ textureInfoDef . index ] . source ! ] ; sheen . setSheenColorTexture ( texture ) ; context . setTextureInfo ( sheen . getSheenColorTextureInfo ( ) ! , textureInfoDef ) ; } if ( sheenDef . sheenRoughnessTexture !== undefined ) { const textureInfoDef = sheenDef . sheenRoughnessTexture ; const texture = context . textures [ textureDefs [ textureInfoDef . index ] . source ! ] ; sheen . setSheenRoughnessTexture ( texture ) ; context . setTextureInfo ( sheen . getSheenRoughnessTextureInfo ( ) ! , textureInfoDef ) ; } } } ) ; return this ; } hidden public write ( context ) { const jsonDoc = context . jsonDoc ; this . document . getRoot ( ) . listMaterials ( ) . forEach ( ( material ) => { const sheen = material . getExtension < Sheen > ( NAME ) ; if ( sheen ) { const materialIndex = context . materialIndexMap . get ( material ) ! ; const materialDef = jsonDoc . json . materials ! [ materialIndex ] ; materialDef . extensions = materialDef . extensions || { } ; const sheenDef = ( materialDef . extensions [ NAME ] = { sheenColorFactor : sheen . getSheenColorFactor ( ) , sheenRoughnessFactor : sheen . getSheenRoughnessFactor ( ) , } as SheenDef ) ; if ( sheen . getSheenColorTexture ( ) ) { const texture = sheen . getSheenColorTexture ( ) ! ; const textureInfo = sheen . getSheenColorTextureInfo ( ) ! ; sheenDef . sheenColorTexture = context . createTextureInfoDef ( texture , textureInfo ) ; } if ( sheen . getSheenRoughnessTexture ( ) ) { const texture = sheen . getSheenRoughnessTexture ( ) ! ; const textureInfo = sheen . getSheenRoughnessTextureInfo ( ) ! ; sheenDef . sheenRoughnessTexture = context . createTextureInfoDef ( texture , textureInfo ) ; } } } ) ; return this ; } }