UNPKG

threepipe

Version:

A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.

226 lines 10.7 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var ClearcoatTintPlugin_1; import { Color } from 'three'; import { AViewerPluginSync } from '../../viewer'; import { uiFolderContainer, uiToggle } from 'uiconfig.js'; import { glsl, serialize } from 'ts-browser-helpers'; import { updateMaterialDefines } from '../../materials'; import { shaderReplaceString, ThreeSerialization } from '../../utils'; /** * Clearcoat Tint Plugin * Adds a material extension to PhysicalMaterial which adds tint and thickness to the built-in clearcoat properties. * It also adds a UI to the material to edit the settings. * It uses WEBGI_materials_clearcoat_tint glTF extension to save the settings in glTF files. * @category Plugins */ let ClearcoatTintPlugin = ClearcoatTintPlugin_1 = class ClearcoatTintPlugin extends AViewerPluginSync { static AddClearcoatTint(material, params) { const ud = material?.userData; if (!ud) return null; if (!ud._clearcoatTint) ud._clearcoatTint = {}; const tf = ud._clearcoatTint; tf.enableTint = true; if (tf.tintColor === undefined) tf.tintColor = '#ffffff'; if (tf.thickness === undefined) tf.thickness = 0.1; if (tf.ior === undefined) tf.ior = 1.5; params && Object.assign(tf, params); if (material.setDirty) material.setDirty(); return tf; } constructor() { super(); this.enabled = true; // private _defines: any = { // // eslint-disable-next-line @typescript-eslint/naming-convention // CLEARCOAT_TINT_DEBUG: false, // } this._uniforms = { ccTintColor: { value: new Color() }, ccThickness: { value: 0. }, ccIor: { value: 0. }, }; // private _multiplyPass?: MultiplyPass this.materialExtension = { parsFragmentSnippet: (_, material) => { if (this.isDisabled() || !material?.userData._clearcoatTint?.enableTint || !(material.clearcoat > 0)) return ''; return glsl ` uniform vec3 ccTintColor; uniform float ccThickness; uniform float ccIor; vec3 clearcoatTint(const in float dotNV, const in float dotNL, const in float clearcoat) { vec3 tint = ( ccThickness > 0. ? 1. - ccTintColor : ccTintColor); // Set thickness < 0 for glow. tint = exp(tint * -(ccThickness * ((dotNL + dotNV) / max(dotNL * dotNV, 1e-3)))); // beer's law return mix(vec3(1.0), tint, clearcoat); } `; }, shaderExtender: (shader, material) => { if (this.isDisabled() || !material?.userData._clearcoatTint?.enableTint || !(material.clearcoat > 0)) return; // Note: clearcoat only considers specular, not diffuse shader.fragmentShader = shaderReplaceString(shader.fragmentShader, 'float dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );', 'float dotNVcc = saturate( dot( geometryClearcoatNormal, -refract(geometryViewDir, geometryClearcoatNormal, 1./ccIor) ) );'); // todo: we are considering all light is coming from env map, but we should consider light coming from light sources by seperating light and env map attenuation shader.fragmentShader = shaderReplaceString(shader.fragmentShader, 'outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;', 'outgoingLight *= clearcoatTint(dotNVcc, dotNVcc, material.clearcoat);\n', { prepend: true }); shader.defines && (shader.defines.USE_UV = ''); }, onObjectRender: (_, material) => { const tfUd = material.userData._clearcoatTint; if (!tfUd?.enableTint) return; this._uniforms.ccTintColor.value.set(tfUd.tintColor); // could be number or string also, apart from Color this._uniforms.ccThickness.value = tfUd.thickness; this._uniforms.ccIor.value = tfUd.ior; updateMaterialDefines({ // ...this._defines, ['CLEARCOAT_TINT_ENABLED']: +!this.isDisabled(), }, material); }, extraUniforms: { // ...this._uniforms, // done in constructor }, computeCacheKey: (material1) => { return (this.isDisabled() ? '0' : '1') + (material1.userData._clearcoatTint?.enableTint ? '1' : '0') + (material1.clearcoat > 0 ? '1' : '0'); }, isCompatible: (material1) => { return material1.isPhysicalMaterial; }, getUiConfig: (material) => { const viewer = this._viewer; if (material.userData._clearcoatTint === undefined) material.userData._clearcoatTint = {}; const state = material.userData._clearcoatTint; const config = { type: 'folder', label: 'Clearcoat Tint', onChange: (ev) => { if (!ev.config) return; this.setDirty(); }, children: [ { type: 'checkbox', label: 'Enabled', get value() { return state.enableTint || false; }, set value(v) { if (v === state.enableTint) return; if (v) { if (!ClearcoatTintPlugin_1.AddClearcoatTint(material)) viewer.dialog.alert('Cannot add clearcoat tint.'); } else { state.enableTint = false; if (material.setDirty) material.setDirty(); } config.uiRefresh?.(true, 'postFrame'); }, }, { type: 'color', label: 'Tint color', hidden: () => !state.enableTint, property: [state, 'tintColor'], }, { type: 'input', label: 'Thickness', hidden: () => !state.enableTint, property: [state, 'thickness'], }, { type: 'slider', bounds: [0.8, 2.5], label: 'IOR', hidden: () => !state.enableTint, property: [state, 'ior'], }, ], }; return config; }, }; this.setDirty = () => { this.materialExtension.setDirty?.(); this._viewer?.setDirty(); }; Object.assign(this.materialExtension.extraUniforms, this._uniforms); } onAdded(v) { super.onAdded(v); v.assetManager.materials.registerMaterialExtension(this.materialExtension); v.assetManager.registerGltfExtension(clearCoatTintGLTFExtension); } onRemove(v) { v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension); v.assetManager.unregisterGltfExtension(clearCoatTintGLTFExtension.name); return super.onRemove(v); } }; ClearcoatTintPlugin.PluginType = 'ClearcoatTintPlugin'; /** * @deprecated - use {@link clearCoatTintGLTFExtension} */ ClearcoatTintPlugin.CLEARCOAT_TINT_GLTF_EXTENSION = 'WEBGI_materials_clearcoat_tint'; __decorate([ uiToggle('Enabled', (that) => ({ onChange: that.setDirty })), serialize() ], ClearcoatTintPlugin.prototype, "enabled", void 0); ClearcoatTintPlugin = ClearcoatTintPlugin_1 = __decorate([ uiFolderContainer('Clearcoat Tint (MatExt)') ], ClearcoatTintPlugin); export { ClearcoatTintPlugin }; /** * ClearcoatTint Materials Extension * * Specification: https://threepipe.org/docs/gltf-extensions/WEBGI_materials_clearcoat_tint.html (todo - fix link) */ class GLTFMaterialsClearcoatTintExtensionImport { constructor(parser) { this.parser = parser; this.name = clearCoatTintGLTFExtension.name; } async extendMaterialParams(materialIndex, materialParams) { const parser = this.parser; const materialDef = parser.json.materials[materialIndex]; if (!materialDef.extensions || !materialDef.extensions[this.name]) return; const extension = materialDef.extensions[this.name]; if (!materialParams.userData) materialParams.userData = {}; ClearcoatTintPlugin.AddClearcoatTint(materialParams); ThreeSerialization.Deserialize(extension, materialParams.userData._clearcoatTint); } } const glTFMaterialsClearcoatTintExtensionExport = (w) => ({ writeMaterial: (material, materialDef) => { if (!material.isMeshStandardMaterial || !material.userData._clearcoatTint?.enableTint) return; materialDef.extensions = materialDef.extensions || {}; const extensionDef = ThreeSerialization.Serialize(material.userData._clearcoatTint); materialDef.extensions[clearCoatTintGLTFExtension.name] = extensionDef; w.extensionsUsed[clearCoatTintGLTFExtension.name] = true; }, }); export const clearCoatTintGLTFExtension = { name: 'WEBGI_materials_clearcoat_tint', import: (p) => new GLTFMaterialsClearcoatTintExtensionImport(p), export: glTFMaterialsClearcoatTintExtensionExport, textures: undefined, }; //# sourceMappingURL=ClearcoatTintPlugin.js.map