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.

113 lines 6.44 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; }; import { updateMaterialDefines } from '../../materials'; import { AViewerPluginSync } from '../../viewer'; import { onChange, serialize } from 'ts-browser-helpers'; import { uiFolderContainer, uiSlider, uiToggle } from 'uiconfig.js'; import { shaderReplaceString } from '../../utils'; import { ShaderChunk } from 'three'; import ParallaxMappingPluginReliefShader from './shaders/ParallaxMappingPlugin.relief.glsl'; /** * Parallax Mapping Plugin * Adds a material extension to PhysicalMaterial which parallax mapping to bump map in the material. * This is a port of Relief Parallax Mapping from [Rabbid76/graphics-snippets](https://github.com/Rabbid76/graphics-snippets/blob/master/html/technique/parallax_005_parallax_relief_mapping_derivative_tbn.html) * @category Plugins */ let ParallaxMappingPlugin = class ParallaxMappingPlugin extends AViewerPluginSync { constructor(enabled = true) { super(); this.enabled = true; this.stepCount = 12; this.binaryStepCount = 3; this.debugNormals = false; this.debugHitHeight = false; this._defines = { ['PARALLAX_NORMAL_MAP_QUALITY']: 0, }; this._bumpMapExtension = { shaderExtender: (shader, material, _renderer) => { if (!material.bumpMap || this.isDisabled()) return; shader.fragmentShader = shader.fragmentShader.replace('#include <normal_fragment_begin>', ''); shader.fragmentShader = shader.fragmentShader.replace('#include <normal_fragment_maps>', ''); shader.fragmentShader = shader.fragmentShader.replace('#include <map_fragment>', '#include <normal_fragment_begin>\n#include <normal_fragment_maps>\n#include <map_fragment>'); for (const s of ['map_fragment', 'alphamap_fragment', 'roughnessmap_fragment', 'metalnessmap_fragment', 'emissivemap_fragment', 'transmission_fragment']) { shader.fragmentShader = shaderReplaceString(shader.fragmentShader, `#include <${s}>`, ShaderChunk[s].replace(/\bv\w+Uv\b/g, 'parallaxUv.xy', { replaceAll: true })); } if (this.debugNormals || this.debugHitHeight) shader.fragmentShader = shaderReplaceString(shader.fragmentShader, // .replace('texture2D( map, parallaxUv.xy )', 'texture2D( map, parallaxUv.xy )') 'texture2D( map, parallaxUv.xy )', this.debugNormals ? 'vec4(normal, 1.); normal = nonPerturbedNormal' : 'vec4(parallaxUv.z,0., 0., 1.)'); shader.fragmentShader = shaderReplaceString(shader.fragmentShader, '#include <normal_fragment_maps>', shaderReplaceString(shaderReplaceString(ShaderChunk.normal_fragment_maps, '#elif defined( USE_NORMALMAP_TANGENTSPACE )', '#elif defined( USE_NORMALMAP_TANGENTSPACE ) && !defined( USE_BUMPMAP )'), 'normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );', // 'diffuseColor.rgb = vec3(0, dHdxy_fwd());' // 'diffuseColor.rgb = CalculateNormal(vUv).rgb;' 'vec3 parallaxUv = reliefParallaxPerturbNormal(faceDirection, normal);')); }, parsFragmentSnippet: () => { return this.isDisabled() ? '' : (ParallaxMappingPluginReliefShader + '\n') .replaceAll('PARALLAX_MAP_STEPS', this.stepCount.toString()) // replacing here to unroll for loop. .replaceAll('PARALLAX_MAP_B_STEPS', this.binaryStepCount.toString()); }, isCompatible: (material) => { return material.isPhysicalMaterial; }, computeCacheKey: material => { return '' + !this.isDisabled() + material.bumpMap?.uuid + this.debugNormals + this.debugHitHeight + this.stepCount.toString() + this.binaryStepCount.toString(); }, onObjectRender: (_object, material, _renderer) => { if (this.isDisabled()) return; // todo: use extraDefines updateMaterialDefines({ ...this._defines, }, material); }, }; this.enabled = enabled; this._updateExtension = this._updateExtension.bind(this); } _updateExtension() { this._bumpMapExtension?.setDirty?.(); this._viewer?.setDirty(); } onAdded(viewer) { viewer.materialManager.registerMaterialExtension(this._bumpMapExtension); return super.onAdded(viewer); } onRemove(viewer) { viewer.materialManager.unregisterMaterialExtension(this._bumpMapExtension); return super.onRemove(viewer); } }; ParallaxMappingPlugin.PluginType = 'ReliefParallaxMapping'; __decorate([ onChange(ParallaxMappingPlugin.prototype._updateExtension), serialize(), uiToggle('Enabled') ], ParallaxMappingPlugin.prototype, "enabled", void 0); __decorate([ uiSlider('Step count', [1, 32], 1), onChange(ParallaxMappingPlugin.prototype._updateExtension), serialize() ], ParallaxMappingPlugin.prototype, "stepCount", void 0); __decorate([ uiSlider('Binary search steps', [1, 8], 1), onChange(ParallaxMappingPlugin.prototype._updateExtension), serialize() ], ParallaxMappingPlugin.prototype, "binaryStepCount", void 0); __decorate([ onChange(ParallaxMappingPlugin.prototype._updateExtension), uiToggle('Debug Normals') ], ParallaxMappingPlugin.prototype, "debugNormals", void 0); __decorate([ onChange(ParallaxMappingPlugin.prototype._updateExtension), uiToggle('Debug Hit Height') ], ParallaxMappingPlugin.prototype, "debugHitHeight", void 0); ParallaxMappingPlugin = __decorate([ uiFolderContainer('Parallax Bump Mapping (MatExt)') ], ParallaxMappingPlugin); export { ParallaxMappingPlugin }; //# sourceMappingURL=ParallaxMappingPlugin.js.map