UNPKG

three

Version:

JavaScript 3D library

536 lines (424 loc) 13.2 kB
import { Vector2 } from '../math/Vector2.js'; import { MeshStandardMaterial } from './MeshStandardMaterial.js'; import { Color } from '../math/Color.js'; import { clamp } from '../math/MathUtils.js'; /** * An extension of the {@link MeshStandardMaterial}, providing more advanced * physically-based rendering properties: * * - Anisotropy: Ability to represent the anisotropic property of materials * as observable with brushed metals. * - Clearcoat: Some materials — like car paints, carbon fiber, and wet surfaces — require * a clear, reflective layer on top of another layer that may be irregular or rough. * Clearcoat approximates this effect, without the need for a separate transparent surface. * - Iridescence: Allows to render the effect where hue varies depending on the viewing * angle and illumination angle. This can be seen on soap bubbles, oil films, or on the * wings of many insects. * - Physically-based transparency: One limitation of {@link Material#opacity} is that highly * transparent materials are less reflective. Physically-based transmission provides a more * realistic option for thin, transparent surfaces like glass. * - Advanced reflectivity: More flexible reflectivity for non-metallic materials. * - Sheen: Can be used for representing cloth and fabric materials. * * As a result of these complex shading features, `MeshPhysicalMaterial` has a * higher performance cost, per pixel, than other three.js materials. Most * effects are disabled by default, and add cost as they are enabled. For * best results, always specify an environment map when using this material. * * @augments MeshStandardMaterial */ class MeshPhysicalMaterial extends MeshStandardMaterial { /** * Constructs a new mesh physical material. * * @param {Object} [parameters] - An object with one or more properties * defining the material's appearance. Any property of the material * (including any property from inherited materials) can be passed * in here. Color values can be passed any type of value accepted * by {@link Color#set}. */ constructor( parameters ) { super(); /** * This flag can be used for type testing. * * @type {boolean} * @readonly * @default true */ this.isMeshPhysicalMaterial = true; this.defines = { 'STANDARD': '', 'PHYSICAL': '' }; this.type = 'MeshPhysicalMaterial'; /** * The rotation of the anisotropy in tangent, bitangent space, measured in radians * counter-clockwise from the tangent. When `anisotropyMap` is present, this * property provides additional rotation to the vectors in the texture. * * @type {number} * @default 1 */ this.anisotropyRotation = 0; /** * Red and green channels represent the anisotropy direction in `[-1, 1]` tangent, * bitangent space, to be rotated by `anisotropyRotation`. The blue channel * contains strength as `[0, 1]` to be multiplied by `anisotropy`. * * @type {?Texture} * @default null */ this.anisotropyMap = null; /** * The red channel of this texture is multiplied against `clearcoat`, * for per-pixel control over a coating's intensity. * * @type {?Texture} * @default null */ this.clearcoatMap = null; /** * Roughness of the clear coat layer, from `0.0` to `1.0`. * * @type {number} * @default 0 */ this.clearcoatRoughness = 0.0; /** * The green channel of this texture is multiplied against * `clearcoatRoughness`, for per-pixel control over a coating's roughness. * * @type {?Texture} * @default null */ this.clearcoatRoughnessMap = null; /** * How much `clearcoatNormalMap` affects the clear coat layer, from * `(0,0)` to `(1,1)`. * * @type {Vector2} * @default (1,1) */ this.clearcoatNormalScale = new Vector2( 1, 1 ); /** * Can be used to enable independent normals for the clear coat layer. * * @type {?Texture} * @default null */ this.clearcoatNormalMap = null; /** * Index-of-refraction for non-metallic materials, from `1.0` to `2.333`. * * @type {number} * @default 1.5 */ this.ior = 1.5; /** * Degree of reflectivity, from `0.0` to `1.0`. Default is `0.5`, which * corresponds to an index-of-refraction of `1.5`. * * This models the reflectivity of non-metallic materials. It has no effect * when `metalness` is `1.0` * * @name MeshPhysicalMaterial#reflectivity * @type {number} * @default 0.5 */ Object.defineProperty( this, 'reflectivity', { get: function () { return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) ); }, set: function ( reflectivity ) { this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity ); } } ); /** * The red channel of this texture is multiplied against `iridescence`, for per-pixel * control over iridescence. * * @type {?Texture} * @default null */ this.iridescenceMap = null; /** * Strength of the iridescence RGB color shift effect, represented by an index-of-refraction. * Between `1.0` to `2.333`. * * @type {number} * @default 1.3 */ this.iridescenceIOR = 1.3; /** *Array of exactly 2 elements, specifying minimum and maximum thickness of the iridescence layer. Thickness of iridescence layer has an equivalent effect of the one `thickness` has on `ior`. * * @type {Array<number,number>} * @default [100,400] */ this.iridescenceThicknessRange = [ 100, 400 ]; /** * A texture that defines the thickness of the iridescence layer, stored in the green channel. * Minimum and maximum values of thickness are defined by `iridescenceThicknessRange` array: * - `0.0` in the green channel will result in thickness equal to first element of the array. * - `1.0` in the green channel will result in thickness equal to second element of the array. * - Values in-between will linearly interpolate between the elements of the array. * * @type {?Texture} * @default null */ this.iridescenceThicknessMap = null; /** * The sheen tint. * * @type {Color} * @default (0,0,0) */ this.sheenColor = new Color( 0x000000 ); /** * The RGB channels of this texture are multiplied against `sheenColor`, for per-pixel control * over sheen tint. * * @type {?Texture} * @default null */ this.sheenColorMap = null; /** * Roughness of the sheen layer, from `0.0` to `1.0`. * * @type {number} * @default 1 */ this.sheenRoughness = 1.0; /** * The alpha channel of this texture is multiplied against `sheenRoughness`, for per-pixel control * over sheen roughness. * * @type {?Texture} * @default null */ this.sheenRoughnessMap = null; /** * The red channel of this texture is multiplied against `transmission`, for per-pixel control over * optical transparency. * * @type {?Texture} * @default null */ this.transmissionMap = null; /** * The thickness of the volume beneath the surface. The value is given in the * coordinate space of the mesh. If the value is `0` the material is * thin-walled. Otherwise the material is a volume boundary. * * @type {number} * @default 0 */ this.thickness = 0; /** * A texture that defines the thickness, stored in the green channel. This will * be multiplied by `thickness`. * * @type {?Texture} * @default null */ this.thicknessMap = null; /** * Density of the medium given as the average distance that light travels in * the medium before interacting with a particle. The value is given in world * space units, and must be greater than zero. * * @type {number} * @default Infinity */ this.attenuationDistance = Infinity; /** * The color that white light turns into due to absorption when reaching the * attenuation distance. * * @type {Color} * @default (1,1,1) */ this.attenuationColor = new Color( 1, 1, 1 ); /** * A float that scales the amount of specular reflection for non-metals only. * When set to zero, the model is effectively Lambertian. From `0.0` to `1.0`. * * @type {number} * @default 1 */ this.specularIntensity = 1.0; /** * The alpha channel of this texture is multiplied against `specularIntensity`, * for per-pixel control over specular intensity. * * @type {?Texture} * @default null */ this.specularIntensityMap = null; /** * Tints the specular reflection at normal incidence for non-metals only. * * @type {Color} * @default (1,1,1) */ this.specularColor = new Color( 1, 1, 1 ); /** * The RGB channels of this texture are multiplied against `specularColor`, * for per-pixel control over specular color. * * @type {?Texture} * @default null */ this.specularColorMap = null; this._anisotropy = 0; this._clearcoat = 0; this._dispersion = 0; this._iridescence = 0; this._sheen = 0.0; this._transmission = 0; this.setValues( parameters ); } /** * The anisotropy strength. * * @type {number} * @default 0 */ get anisotropy() { return this._anisotropy; } set anisotropy( value ) { if ( this._anisotropy > 0 !== value > 0 ) { this.version ++; } this._anisotropy = value; } /** * Represents the intensity of the clear coat layer, from `0.0` to `1.0`. Use * clear coat related properties to enable multilayer materials that have a * thin translucent layer over the base layer. * * @type {number} * @default 0 */ get clearcoat() { return this._clearcoat; } set clearcoat( value ) { if ( this._clearcoat > 0 !== value > 0 ) { this.version ++; } this._clearcoat = value; } /** * The intensity of the iridescence layer, simulating RGB color shift based on the angle between * the surface and the viewer, from `0.0` to `1.0`. * * @type {number} * @default 0 */ get iridescence() { return this._iridescence; } set iridescence( value ) { if ( this._iridescence > 0 !== value > 0 ) { this.version ++; } this._iridescence = value; } /** * Defines the strength of the angular separation of colors (chromatic aberration) transmitting * through a relatively clear volume. Any value zero or larger is valid, the typical range of * realistic values is `[0, 1]`. This property can be only be used with transmissive objects. * * @type {number} * @default 0 */ get dispersion() { return this._dispersion; } set dispersion( value ) { if ( this._dispersion > 0 !== value > 0 ) { this.version ++; } this._dispersion = value; } /** * The intensity of the sheen layer, from `0.0` to `1.0`. * * @type {number} * @default 0 */ get sheen() { return this._sheen; } set sheen( value ) { if ( this._sheen > 0 !== value > 0 ) { this.version ++; } this._sheen = value; } /** * Degree of transmission (or optical transparency), from `0.0` to `1.0`. * * Thin, transparent or semitransparent, plastic or glass materials remain * largely reflective even if they are fully transmissive. The transmission * property can be used to model these materials. * * When transmission is non-zero, `opacity` should be set to `1`. * * @type {number} * @default 0 */ get transmission() { return this._transmission; } set transmission( value ) { if ( this._transmission > 0 !== value > 0 ) { this.version ++; } this._transmission = value; } copy( source ) { super.copy( source ); this.defines = { 'STANDARD': '', 'PHYSICAL': '' }; this.anisotropy = source.anisotropy; this.anisotropyRotation = source.anisotropyRotation; this.anisotropyMap = source.anisotropyMap; this.clearcoat = source.clearcoat; this.clearcoatMap = source.clearcoatMap; this.clearcoatRoughness = source.clearcoatRoughness; this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; this.clearcoatNormalMap = source.clearcoatNormalMap; this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); this.dispersion = source.dispersion; this.ior = source.ior; this.iridescence = source.iridescence; this.iridescenceMap = source.iridescenceMap; this.iridescenceIOR = source.iridescenceIOR; this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ]; this.iridescenceThicknessMap = source.iridescenceThicknessMap; this.sheen = source.sheen; this.sheenColor.copy( source.sheenColor ); this.sheenColorMap = source.sheenColorMap; this.sheenRoughness = source.sheenRoughness; this.sheenRoughnessMap = source.sheenRoughnessMap; this.transmission = source.transmission; this.transmissionMap = source.transmissionMap; this.thickness = source.thickness; this.thicknessMap = source.thicknessMap; this.attenuationDistance = source.attenuationDistance; this.attenuationColor.copy( source.attenuationColor ); this.specularIntensity = source.specularIntensity; this.specularIntensityMap = source.specularIntensityMap; this.specularColor.copy( source.specularColor ); this.specularColorMap = source.specularColorMap; return this; } } export { MeshPhysicalMaterial };