UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

450 lines (409 loc) 16.9 kB
import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor, dispersion } from '../../nodes/core/PropertyNode.js'; import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialSpecularIntensity, materialSpecularColor, materialAnisotropy, materialIOR, materialTransmission, materialThickness, materialAttenuationDistance, materialAttenuationColor, materialDispersion } from '../../nodes/accessors/MaterialNode.js'; import { float, vec2, vec3, If } from '../../nodes/tsl/TSLBase.js'; import getRoughness from '../../nodes/functions/material/getRoughness.js'; import { TBNViewMatrix } from '../../nodes/accessors/AccessorsUtils.js'; import PhysicalLightingModel from '../../nodes/functions/PhysicalLightingModel.js'; import MeshStandardNodeMaterial from './MeshStandardNodeMaterial.js'; import { mix, pow2, min } from '../../nodes/math/MathNode.js'; import { MeshPhysicalMaterial } from '../MeshPhysicalMaterial.js'; const _defaultValues = /*@__PURE__*/new MeshPhysicalMaterial(); /** * Node material version of {@link MeshPhysicalMaterial}. * * @augments MeshStandardNodeMaterial */ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { static get type() { return 'MeshPhysicalNodeMaterial'; } /** * Constructs a new mesh physical node material. * * @param {Object} [parameters] - The configuration parameter. */ constructor(parameters) { super(); /** * This flag can be used for type testing. * * @type {boolean} * @readonly * @default true */ this.isMeshPhysicalNodeMaterial = true; /** * The clearcoat of physical materials is by default inferred from the `clearcoat` * and `clearcoatMap` properties. This node property allows to overwrite the default * and define the clearcoat with a node instead. * * If you don't want to overwrite the clearcoat but modify the existing * value instead, use {@link materialClearcoat}. * * @type {?Node<float>} * @default null */ this.clearcoatNode = null; /** * The clearcoat roughness of physical materials is by default inferred from the `clearcoatRoughness` * and `clearcoatRoughnessMap` properties. This node property allows to overwrite the default * and define the clearcoat roughness with a node instead. * * If you don't want to overwrite the clearcoat roughness but modify the existing * value instead, use {@link materialClearcoatRoughness}. * * @type {?Node<float>} * @default null */ this.clearcoatRoughnessNode = null; /** * The clearcoat normal of physical materials is by default inferred from the `clearcoatNormalMap` * property. This node property allows to overwrite the default * and define the clearcoat normal with a node instead. * * If you don't want to overwrite the clearcoat normal but modify the existing * value instead, use {@link materialClearcoatNormal}. * * @type {?Node<vec3>} * @default null */ this.clearcoatNormalNode = null; /** * The sheen of physical materials is by default inferred from the `sheen`, `sheenColor` * and `sheenColorMap` properties. This node property allows to overwrite the default * and define the sheen with a node instead. * * If you don't want to overwrite the sheen but modify the existing * value instead, use {@link materialSheen}. * * @type {?Node<vec3>} * @default null */ this.sheenNode = null; /** * The sheen roughness of physical materials is by default inferred from the `sheenRoughness` and * `sheenRoughnessMap` properties. This node property allows to overwrite the default * and define the sheen roughness with a node instead. * * If you don't want to overwrite the sheen roughness but modify the existing * value instead, use {@link materialSheenRoughness}. * * @type {?Node<float>} * @default null */ this.sheenRoughnessNode = null; /** * The iridescence of physical materials is by default inferred from the `iridescence` * property. This node property allows to overwrite the default * and define the iridescence with a node instead. * * If you don't want to overwrite the iridescence but modify the existing * value instead, use {@link materialIridescence}. * * @type {?Node<float>} * @default null */ this.iridescenceNode = null; /** * The iridescence IOR of physical materials is by default inferred from the `iridescenceIOR` * property. This node property allows to overwrite the default * and define the iridescence IOR with a node instead. * * If you don't want to overwrite the iridescence IOR but modify the existing * value instead, use {@link materialIridescenceIOR}. * * @type {?Node<float>} * @default null */ this.iridescenceIORNode = null; /** * The iridescence thickness of physical materials is by default inferred from the `iridescenceThicknessRange` * and `iridescenceThicknessMap` properties. This node property allows to overwrite the default * and define the iridescence thickness with a node instead. * * If you don't want to overwrite the iridescence thickness but modify the existing * value instead, use {@link materialIridescenceThickness}. * * @type {?Node<float>} * @default null */ this.iridescenceThicknessNode = null; /** * The specular intensity of physical materials is by default inferred from the `specularIntensity` * and `specularIntensityMap` properties. This node property allows to overwrite the default * and define the specular intensity with a node instead. * * If you don't want to overwrite the specular intensity but modify the existing * value instead, use {@link materialSpecularIntensity}. * * @type {?Node<float>} * @default null */ this.specularIntensityNode = null; /** * The specular color of physical materials is by default inferred from the `specularColor` * and `specularColorMap` properties. This node property allows to overwrite the default * and define the specular color with a node instead. * * If you don't want to overwrite the specular color but modify the existing * value instead, use {@link materialSpecularColor}. * * @type {?Node<vec3>} * @default null */ this.specularColorNode = null; /** * The ior of physical materials is by default inferred from the `ior` * property. This node property allows to overwrite the default * and define the ior with a node instead. * * If you don't want to overwrite the ior but modify the existing * value instead, use {@link materialIOR}. * * @type {?Node<float>} * @default null */ this.iorNode = null; /** * The transmission of physical materials is by default inferred from the `transmission` and * `transmissionMap` properties. This node property allows to overwrite the default * and define the transmission with a node instead. * * If you don't want to overwrite the transmission but modify the existing * value instead, use {@link materialTransmission}. * * @type {?Node<float>} * @default null */ this.transmissionNode = null; /** * The thickness of physical materials is by default inferred from the `thickness` and * `thicknessMap` properties. This node property allows to overwrite the default * and define the thickness with a node instead. * * If you don't want to overwrite the thickness but modify the existing * value instead, use {@link materialThickness}. * * @type {?Node<float>} * @default null */ this.thicknessNode = null; /** * The attenuation distance of physical materials is by default inferred from the * `attenuationDistance` property. This node property allows to overwrite the default * and define the attenuation distance with a node instead. * * If you don't want to overwrite the attenuation distance but modify the existing * value instead, use {@link materialAttenuationDistance}. * * @type {?Node<float>} * @default null */ this.attenuationDistanceNode = null; /** * The attenuation color of physical materials is by default inferred from the * `attenuationColor` property. This node property allows to overwrite the default * and define the attenuation color with a node instead. * * If you don't want to overwrite the attenuation color but modify the existing * value instead, use {@link materialAttenuationColor}. * * @type {?Node<vec3>} * @default null */ this.attenuationColorNode = null; /** * The dispersion of physical materials is by default inferred from the * `dispersion` property. This node property allows to overwrite the default * and define the dispersion with a node instead. * * If you don't want to overwrite the dispersion but modify the existing * value instead, use {@link materialDispersion}. * * @type {?Node<float>} * @default null */ this.dispersionNode = null; /** * The anisotropy of physical materials is by default inferred from the * `anisotropy` property. This node property allows to overwrite the default * and define the anisotropy with a node instead. * * If you don't want to overwrite the anisotropy but modify the existing * value instead, use {@link materialAnisotropy}. * * @type {?Node<float>} * @default null */ this.anisotropyNode = null; this.setDefaultValues(_defaultValues); this.setValues(parameters); } /** * Whether the lighting model should use clearcoat or not. * * @type {boolean} * @default true */ get useClearcoat() { return this.clearcoat > 0 || this.clearcoatNode !== null; } /** * Whether the lighting model should use iridescence or not. * * @type {boolean} * @default true */ get useIridescence() { return this.iridescence > 0 || this.iridescenceNode !== null; } /** * Whether the lighting model should use sheen or not. * * @type {boolean} * @default true */ get useSheen() { return this.sheen > 0 || this.sheenNode !== null; } /** * Whether the lighting model should use anisotropy or not. * * @type {boolean} * @default true */ get useAnisotropy() { return this.anisotropy > 0 || this.anisotropyNode !== null; } /** * Whether the lighting model should use transmission or not. * * @type {boolean} * @default true */ get useTransmission() { return this.transmission > 0 || this.transmissionNode !== null; } /** * Whether the lighting model should use dispersion or not. * * @type {boolean} * @default true */ get useDispersion() { return this.dispersion > 0 || this.dispersionNode !== null; } /** * Setups the specular related node variables. */ setupSpecular() { const iorNode = this.iorNode ? float(this.iorNode) : materialIOR; ior.assign(iorNode); specularColor.assign(mix(min(pow2(ior.sub(1.0).div(ior.add(1.0))).mul(materialSpecularColor), vec3(1.0)).mul(materialSpecularIntensity), diffuseColor.rgb, metalness)); specularF90.assign(mix(materialSpecularIntensity, 1.0, metalness)); } /** * Setups the lighting model. * * @return {PhysicalLightingModel} The lighting model. */ setupLightingModel( /*builder*/ ) { return new PhysicalLightingModel(this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion); } /** * Setups the physical specific node variables. * * @param {NodeBuilder} builder - The current node builder. */ setupVariants(builder) { super.setupVariants(builder); // CLEARCOAT if (this.useClearcoat) { const clearcoatNode = this.clearcoatNode ? float(this.clearcoatNode) : materialClearcoat; const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float(this.clearcoatRoughnessNode) : materialClearcoatRoughness; clearcoat.assign(clearcoatNode); clearcoatRoughness.assign(getRoughness({ roughness: clearcoatRoughnessNode })); } // SHEEN if (this.useSheen) { const sheenNode = this.sheenNode ? vec3(this.sheenNode) : materialSheen; const sheenRoughnessNode = this.sheenRoughnessNode ? float(this.sheenRoughnessNode) : materialSheenRoughness; sheen.assign(sheenNode); sheenRoughness.assign(sheenRoughnessNode); } // IRIDESCENCE if (this.useIridescence) { const iridescenceNode = this.iridescenceNode ? float(this.iridescenceNode) : materialIridescence; const iridescenceIORNode = this.iridescenceIORNode ? float(this.iridescenceIORNode) : materialIridescenceIOR; const iridescenceThicknessNode = this.iridescenceThicknessNode ? float(this.iridescenceThicknessNode) : materialIridescenceThickness; iridescence.assign(iridescenceNode); iridescenceIOR.assign(iridescenceIORNode); iridescenceThickness.assign(iridescenceThicknessNode); } // ANISOTROPY if (this.useAnisotropy) { const anisotropyV = (this.anisotropyNode ? vec2(this.anisotropyNode) : materialAnisotropy).toVar(); anisotropy.assign(anisotropyV.length()); If(anisotropy.equal(0.0), () => { anisotropyV.assign(vec2(1.0, 0.0)); }).Else(() => { anisotropyV.divAssign(vec2(anisotropy)); anisotropy.assign(anisotropy.saturate()); }); // Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy. alphaT.assign(anisotropy.pow2().mix(roughness.pow2(), 1.0)); anisotropyT.assign(TBNViewMatrix[0].mul(anisotropyV.x).add(TBNViewMatrix[1].mul(anisotropyV.y))); anisotropyB.assign(TBNViewMatrix[1].mul(anisotropyV.x).sub(TBNViewMatrix[0].mul(anisotropyV.y))); } // TRANSMISSION if (this.useTransmission) { const transmissionNode = this.transmissionNode ? float(this.transmissionNode) : materialTransmission; const thicknessNode = this.thicknessNode ? float(this.thicknessNode) : materialThickness; const attenuationDistanceNode = this.attenuationDistanceNode ? float(this.attenuationDistanceNode) : materialAttenuationDistance; const attenuationColorNode = this.attenuationColorNode ? vec3(this.attenuationColorNode) : materialAttenuationColor; transmission.assign(transmissionNode); thickness.assign(thicknessNode); attenuationDistance.assign(attenuationDistanceNode); attenuationColor.assign(attenuationColorNode); if (this.useDispersion) { const dispersionNode = this.dispersionNode ? float(this.dispersionNode) : materialDispersion; dispersion.assign(dispersionNode); } } } /** * Setups the clearcoat normal node. * * @return {Node<vec3>} The clearcoat normal. */ setupClearcoatNormal() { return this.clearcoatNormalNode ? vec3(this.clearcoatNormalNode) : materialClearcoatNormal; } setup(builder) { builder.context.setupClearcoatNormal = () => this.setupClearcoatNormal(builder); super.setup(builder); } copy(source) { this.clearcoatNode = source.clearcoatNode; this.clearcoatRoughnessNode = source.clearcoatRoughnessNode; this.clearcoatNormalNode = source.clearcoatNormalNode; this.sheenNode = source.sheenNode; this.sheenRoughnessNode = source.sheenRoughnessNode; this.iridescenceNode = source.iridescenceNode; this.iridescenceIORNode = source.iridescenceIORNode; this.iridescenceThicknessNode = source.iridescenceThicknessNode; this.specularIntensityNode = source.specularIntensityNode; this.specularColorNode = source.specularColorNode; this.transmissionNode = source.transmissionNode; this.thicknessNode = source.thicknessNode; this.attenuationDistanceNode = source.attenuationDistanceNode; this.attenuationColorNode = source.attenuationColorNode; this.dispersionNode = source.dispersionNode; this.anisotropyNode = source.anisotropyNode; return super.copy(source); } } export default MeshPhysicalNodeMaterial;