| @@ -9,7 +9,7 @@ | |||
| "version": "0.0.43", | |||
| "license": "Apache-2.0", | |||
| "dependencies": { | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1006/package.tgz", | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.158.1002/package.tgz", | |||
| "@types/webxr": "^0.5.1", | |||
| "@types/wicg-file-system-access": "^2020.9.5", | |||
| "popmotion": "^11.0.5", | |||
| @@ -36,7 +36,7 @@ | |||
| "rimraf": "^5.0.1", | |||
| "rollup-plugin-glsl": "^1.3.0", | |||
| "rollup-plugin-license": "^3.0.1", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1007/package.tgz", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.158.1001/package.tgz", | |||
| "tslib": "^2.5.0", | |||
| "typedoc": "^0.28.4", | |||
| "typescript": "5.8.3", | |||
| @@ -50,7 +50,7 @@ | |||
| "win-node-env": "^0.6.1" | |||
| }, | |||
| "peerDependencies": { | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1007/package.tgz" | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.158.1001/package.tgz" | |||
| }, | |||
| "peerDependenciesMeta": { | |||
| "three": { | |||
| @@ -2398,14 +2398,15 @@ | |||
| "version": "0.17.3", | |||
| "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", | |||
| "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==", | |||
| "dev": true, | |||
| "license": "MIT" | |||
| }, | |||
| "node_modules/@types/three": { | |||
| "version": "0.157.1006", | |||
| "resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1006/package.tgz", | |||
| "integrity": "sha512-WiV0kRvPyPK3KEOGshnPDbgJzfa/YozkFSSfVu32WgFYp9hiSSVQK8wROq5We/DTWs8BmnyWuh7lzbz/4DC3jQ==", | |||
| "version": "0.158.1002", | |||
| "resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.158.1002/package.tgz", | |||
| "integrity": "sha512-oS0ZcdGgVafCcZRgLi3c6+dS/7lrw3BsIfDbDoWINeu5PylZy/VRljGpFj13K/bQ7KT1RfUhNlrKW7LBLgNYcQ==", | |||
| "dependencies": { | |||
| "@types/stats.js": "*", | |||
| "@types/webxr": "*", | |||
| "fflate": "~0.6.10", | |||
| "meshoptimizer": "~0.18.1" | |||
| } | |||
| @@ -10043,9 +10044,9 @@ | |||
| "license": "MIT" | |||
| }, | |||
| "node_modules/three": { | |||
| "version": "0.157.1007", | |||
| "resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1007/package.tgz", | |||
| "integrity": "sha512-VjnxBF9JRjkFrqnHcrpa6VuOHSPyQzzLSYBUrPq0qJZmHhTVo4ns6MmZ8TA0v0kCu9pPNILDH9ZBY5d84v4UPA==", | |||
| "version": "0.158.1001", | |||
| "resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.158.1001/package.tgz", | |||
| "integrity": "sha512-yrzyMBxiKMIsr3gVD+K27L62soJHSDqAihpU+FokWGQGZ01+8jW1BdBb5zkC1Jwt6J7izY2/706t64uZu95wMw==", | |||
| "dev": true, | |||
| "license": "MIT" | |||
| }, | |||
| @@ -110,7 +110,7 @@ | |||
| "rimraf": "^5.0.1", | |||
| "rollup-plugin-glsl": "^1.3.0", | |||
| "rollup-plugin-license": "^3.0.1", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1007/package.tgz", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.158.1001/package.tgz", | |||
| "tslib": "^2.5.0", | |||
| "typedoc": "^0.28.4", | |||
| "typescript": "5.8.3", | |||
| @@ -121,7 +121,7 @@ | |||
| "vitepress-plugin-nprogress": "^0.0.4" | |||
| }, | |||
| "dependencies": { | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1006/package.tgz", | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.158.1002/package.tgz", | |||
| "@types/webxr": "^0.5.1", | |||
| "@types/wicg-file-system-access": "^2020.9.5", | |||
| "popmotion": "^11.0.5", | |||
| @@ -130,7 +130,7 @@ | |||
| "uiconfig.js": "^0.1.3" | |||
| }, | |||
| "peerDependencies": { | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1007/package.tgz" | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.158.1001/package.tgz" | |||
| }, | |||
| "peerDependenciesMeta": { | |||
| "three": { | |||
| @@ -141,10 +141,10 @@ | |||
| "dependencies": { | |||
| "uiconfig.js": "^0.1.3", | |||
| "ts-browser-helpers": "^0.16.2", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1007/package.tgz", | |||
| "three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.157.1007.tar.gz", | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1006/package.tgz", | |||
| "@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.157.1006.tar.gz", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.158.1001/package.tgz", | |||
| "three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.158.1002.tar.gz", | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.158.1002/package.tgz", | |||
| "@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.158.1002.tar.gz", | |||
| "@types/three-pkg": "https://gitpkg.now.sh/repalash/three-ts-types/types/three?modded_three" | |||
| }, | |||
| "local_dependencies": { | |||
| @@ -83,6 +83,20 @@ export class MaterialManager<TEventMap extends object = object> extends EventDis | |||
| const lastColorManagementEnabled = ColorManagement.enabled | |||
| if (legacyColors) ColorManagement.enabled = false | |||
| // bump map scale fix | |||
| // https://github.com/repalash/three.js/commit/7b13bb515866f6a002928bd28d0a793cafeaeb1a | |||
| const legacyBumpScale = (oldMaterial as any)?.metadata && (oldMaterial as any)?.metadata.version <= 4.6 | |||
| if (legacyBumpScale && (oldMaterial as any)?.bumpScale !== undefined && (oldMaterial as any)?.bumpMap) { | |||
| // if (Math.abs((oldMaterial as any).bumpScale) > 0.01) { | |||
| // (oldMaterial as any).bumpScale *= 430 // test model - http://asset-samples.threepipe.org/tests/bumpmap_normalize_migrate.glb | |||
| // console.warn('MaterialManager: Old format material loaded, bump map scaled by 430, it might be incorrect.', (oldMaterial as any).bumpScale) | |||
| // } else { | |||
| console.warn('MaterialManager: Old format material loaded, bump map might be incorrect.', oldMaterial, (oldMaterial as any).bumpScale) | |||
| // } | |||
| } | |||
| const material = template.generator(template.params || {}) | |||
| if (oldMaterial && material) material.setValues(oldMaterial, true) | |||
| @@ -14,7 +14,6 @@ import { | |||
| GLTFObject3DExtrasExtension, | |||
| GLTFViewerConfigExtension, | |||
| } from '../gltf' | |||
| import {GLTFMeshGpuInstancingExporter} from '../../three/utils/gpu-instancing' | |||
| export interface GLTFExporter2Options { | |||
| /** | |||
| @@ -204,7 +203,7 @@ export class GLTFExporter2 extends GLTFExporter implements IExportParser { | |||
| GLTFMaterialsDisplacementMapExtension.Export, | |||
| GLTFMaterialsLightMapExtension.Export, | |||
| GLTFMaterialsAlphaMapExtension.Export, | |||
| (w)=>new GLTFMeshGpuInstancingExporter(w), | |||
| // (w)=>new GLTFMeshGpuInstancingExporter(w), | |||
| ] | |||
| setup(viewer: ThreeViewer, extraExtensions?: ((parser: GLTFWriter2) => GLTFExporterPlugin)[]): this { | |||
| @@ -6,6 +6,17 @@ import {ThreeSerialization} from '../../utils' | |||
| export class GLTFWriter2 extends GLTFExporter.Utils.GLTFWriter { | |||
| protected _assetVersion: number | |||
| readonly TPAssetVersion = 1 | |||
| constructor() { | |||
| super() | |||
| // slightly increment the version to be safe if three.js forgot to update the version | |||
| this._assetVersion = parseFloat(this.json.asset.version) + 0.001 * this.TPAssetVersion | |||
| this.json.asset.version = this._assetVersion.toString() | |||
| } | |||
| declare options: GLTFExporterOptions & { | |||
| externalImagesInExtras: boolean, | |||
| exporterOptions: GLTFExporter2Options | |||
| @@ -1,6 +1,6 @@ | |||
| import type {GLTF, GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | |||
| import {ThreeSerialization} from '../../utils/serialization' | |||
| import {DoubleSide, Material} from 'three' | |||
| import {Color, DoubleSide, Material} from 'three' | |||
| import type {GLTFExporterPlugin, GLTFWriter} from 'three/examples/jsm/exporters/GLTFExporter' | |||
| import {ITexture} from '../../core' | |||
| @@ -52,6 +52,15 @@ export class GLTFMaterialExtrasExtension { | |||
| if (ext.envMapIntensity !== undefined) o.envMapIntensity = ext.envMapIntensity // for when separateEnvMapIntensity is true | |||
| // if (ext.envMapSlotKey !== undefined) o.envMapSlotKey = ext.envMapSlotKey // in userdata | |||
| if (ext.blendSrc !== undefined) o.blendSrc = ext.blendSrc | |||
| if (ext.blendDst !== undefined) o.blendDst = ext.blendDst | |||
| if (ext.blendEquation !== undefined) o.blendEquation = ext.blendEquation | |||
| if (ext.blendSrcAlpha !== undefined) o.blendSrcAlpha = ext.blendSrcAlpha | |||
| if (ext.blendDstAlpha !== undefined) o.blendDstAlpha = ext.blendDstAlpha | |||
| if (ext.blendEquationAlpha !== undefined) o.blendEquationAlpha = ext.blendEquationAlpha | |||
| if (ext.blendColor !== undefined && o.blendColor !== undefined) (o.blendColor as Color).setHex(ext.blendColor) | |||
| if (ext.blendAlpha !== undefined) o.blendAlpha = ext.blendAlpha | |||
| // if (ext.stencilWrite !== undefined) o.stencilWrite = ext.stencilWrite | |||
| // if (ext.stencilWriteMask !== undefined) o.stencilWriteMask = ext.stencilWriteMask | |||
| // if (ext.stencilFunc !== undefined) o.stencilFunc = ext.stencilFunc | |||
| @@ -164,6 +173,15 @@ export class GLTFMaterialExtrasExtension { | |||
| if (material.envMapIntensity !== undefined) dat.envMapIntensity = material.envMapIntensity // for when separateEnvMapIntensity is true | |||
| // if (material.envMapSlotKey !== undefined) dat.envMapSlotKey = material.envMapSlotKey // in userData | |||
| if (material.blendSrc !== undefined) dat.blendSrc = material.blendSrc | |||
| if (material.blendDst !== undefined) dat.blendDst = material.blendDst | |||
| if (material.blendEquation !== undefined) dat.blendEquation = material.blendEquation | |||
| if (material.blendSrcAlpha !== undefined) dat.blendSrcAlpha = material.blendSrcAlpha | |||
| if (material.blendDstAlpha !== undefined) dat.blendDstAlpha = material.blendDstAlpha | |||
| if (material.blendEquationAlpha !== undefined) dat.blendEquationAlpha = material.blendEquationAlpha | |||
| if (material.blendColor !== undefined) dat.blendColor = (material.blendColor as Color).getHex() | |||
| if (material.blendAlpha !== undefined) dat.blendAlpha = material.blendAlpha | |||
| // if (material.stencilWrite !== undefined) dat.stencilWrite = material.stencilWrite | |||
| // if (material.stencilWriteMask !== undefined) dat.stencilWriteMask = material.stencilWriteMask | |||
| // if (material.stencilFunc !== undefined) dat.stencilFunc = material.stencilFunc | |||
| @@ -146,6 +146,32 @@ export class GLTFLoader2 extends GLTFLoader implements ILoader<GLTF, Object3D|un | |||
| if (res.userData) scene.userData.gltfExtras = res.userData // todo: put back in gltf in GLTFExporter2 | |||
| if (res.cameras) res.cameras.forEach(c => !c.parent && scene.add(c)) | |||
| if (res.asset) scene.userData.gltfAsset = res.asset // todo: put back in gltf in GLTFExporter2 | |||
| // todo | |||
| if (res.asset?.version) { | |||
| const version = parseFloat(res.asset.version) | |||
| if (version <= 2.0) { | |||
| // bump map scale fix | |||
| // https://github.com/repalash/three.js/commit/7b13bb515866f6a002928bd28d0a793cafeaeb1a | |||
| // const bounds = new Box3B().expandByObject(scene) | |||
| // const size = bounds.getSize(new Vector3()).length() / 2 | |||
| const fixBump = (material: any) => { | |||
| if (!material || !material.bumpMap || material.bumpScale === undefined) return | |||
| // if (Math.abs(material.bumpScale) > 0.01) { | |||
| // material.bumpScale *= 430 / Math.max(size, 0.1) // test model - http://asset-samples.threepipe.org/tests/bumpmap_normalize_migrate.glb | |||
| // console.warn(`GLTFLoader2: Old format material loaded, bump map scaled by ${430 / Math.max(size, 0.1)}, it might be incorrect.`, material, material.bumpScale) | |||
| // } else { | |||
| console.warn('GLTFLoader2: Old format material loaded, bump map might be incorrect.', material, material.bumpScale) | |||
| // } | |||
| } | |||
| scene?.traverse((obj: any)=>{ | |||
| if (!obj?.material) return | |||
| const mats = Array.isArray(obj.material) ? obj.material : [obj.material] | |||
| mats.forEach(fixBump) | |||
| }) | |||
| } | |||
| } | |||
| return scene | |||
| } | |||
| @@ -5,7 +5,7 @@ import { | |||
| AdditiveBlending, | |||
| AlwaysDepth, | |||
| BackSide, | |||
| Blending, | |||
| Blending, CustomBlending, | |||
| DepthModes, | |||
| DoubleSide, | |||
| EqualDepth, | |||
| @@ -21,9 +21,24 @@ import { | |||
| NormalMapTypes, | |||
| NotEqualDepth, | |||
| ObjectSpaceNormalMap, | |||
| OneFactor, | |||
| OneMinusDstAlphaFactor, | |||
| OneMinusDstColorFactor, | |||
| OneMinusSrcAlphaFactor, | |||
| OneMinusSrcColorFactor, | |||
| Side, | |||
| SrcAlphaFactor, | |||
| SrcAlphaSaturateFactor, | |||
| SrcColorFactor, | |||
| SubtractiveBlending, | |||
| TangentSpaceNormalMap, | |||
| ZeroFactor, | |||
| BlendingEquation, | |||
| BlendingSrcFactor, | |||
| MinEquation, | |||
| ConstantAlphaFactor, ConstantColorFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, | |||
| ReverseSubtractEquation, | |||
| SubtractEquation, AddEquation, MaxEquation, DstAlphaFactor, DstColorFactor, | |||
| } from 'three' | |||
| import {downloadBlob, uploadFile} from 'ts-browser-helpers' | |||
| import {PhysicalMaterial} from './PhysicalMaterial' | |||
| @@ -140,11 +155,108 @@ export const iMaterialUI = { | |||
| ['Additive', AdditiveBlending], | |||
| ['Subtractive', SubtractiveBlending], | |||
| ['Multiply', MultiplyBlending], | |||
| ['Custom', CustomBlending], | |||
| ] as [string, Blending][]).map(value => ({ | |||
| label: value[0], | |||
| value: value[1], | |||
| })), | |||
| }, | |||
| { | |||
| type: 'dropdown', | |||
| hidden: ()=>material.blending !== CustomBlending, | |||
| property: [material, 'blendingEquation'], | |||
| children: ([ | |||
| ['Add', AddEquation], | |||
| ['Subtract', SubtractEquation], | |||
| ['Reverse Subtract', ReverseSubtractEquation], | |||
| ['Min', MinEquation], | |||
| ['Max', MaxEquation], | |||
| ] as [string, BlendingEquation][]).map(value => ({ | |||
| label: value[0], | |||
| value: value[1], | |||
| })), | |||
| }, | |||
| { | |||
| type: 'dropdown', | |||
| property: [material, 'blendSrc'], | |||
| hidden: ()=>material.blending !== CustomBlending, | |||
| children: ([ | |||
| ['Zero', ZeroFactor], | |||
| ['One', OneFactor], | |||
| ['Src Color', SrcColorFactor], | |||
| ['One Minus Src Color', OneMinusSrcColorFactor], | |||
| ['Src Alpha', SrcAlphaFactor], | |||
| ['One Minus Src Alpha', OneMinusSrcAlphaFactor], | |||
| ['Dst Alpha', DstAlphaFactor], | |||
| ['One Minus Dst Alpha', OneMinusDstAlphaFactor], | |||
| ['Dst Color', DstColorFactor], | |||
| ['One Minus Dst Color', OneMinusDstColorFactor], | |||
| ['Src Alpha Saturate', SrcAlphaSaturateFactor], | |||
| ['Constant Color', ConstantColorFactor], | |||
| ['One Minus Constant Color', OneMinusConstantColorFactor], | |||
| ['Constant Alpha', ConstantAlphaFactor], | |||
| ['One Minus Constant Alpha', OneMinusConstantAlphaFactor], | |||
| ] as [string, BlendingSrcFactor][]).map(value => ({ | |||
| label: value[0], | |||
| value: value[1], | |||
| })), | |||
| }, | |||
| { | |||
| type: 'dropdown', | |||
| property: [material, 'blendDst'], | |||
| hidden: ()=>material.blending !== CustomBlending, | |||
| children: ([ | |||
| ['Zero', ZeroFactor], | |||
| ['One', OneFactor], | |||
| ['Src Color', SrcColorFactor], | |||
| ['One Minus Src Color', OneMinusSrcColorFactor], | |||
| ['Src Alpha', SrcAlphaFactor], | |||
| ['One Minus Src Alpha', OneMinusSrcAlphaFactor], | |||
| ['Dst Alpha', DstAlphaFactor], | |||
| ['One Minus Dst Alpha', OneMinusDstAlphaFactor], | |||
| ['Dst Color', DstColorFactor], | |||
| ['One Minus Dst Color', OneMinusDstColorFactor], | |||
| // ['Src Alpha Saturate', SrcAlphaSaturateFactor], | |||
| ['Constant Color', ConstantColorFactor], | |||
| ['One Minus Constant Color', OneMinusConstantColorFactor], | |||
| ['Constant Alpha', ConstantAlphaFactor], | |||
| ['One Minus Constant Alpha', OneMinusConstantAlphaFactor], | |||
| ] as [string, BlendingSrcFactor][]).map(value => ({ | |||
| label: value[0], | |||
| value: value[1], | |||
| })), | |||
| }, | |||
| { | |||
| type: 'slider', | |||
| bounds: [0, 1], | |||
| hidden: ()=>material.blending !== CustomBlending, | |||
| property: [material, 'blendSrcAlpha'], | |||
| }, | |||
| { | |||
| type: 'slider', | |||
| bounds: [0, 1], | |||
| hidden: ()=>material.blending !== CustomBlending, | |||
| property: [material, 'blendDstAlpha'], | |||
| }, | |||
| { | |||
| type: 'color', | |||
| hidden: ()=>material.blending !== CustomBlending || | |||
| material.blendSrc !== ConstantColorFactor && | |||
| material.blendSrc !== OneMinusConstantColorFactor && | |||
| material.blendDst !== ConstantColorFactor && | |||
| material.blendDst !== OneMinusConstantColorFactor, | |||
| property: [material, 'blendColor'], | |||
| }, | |||
| { | |||
| type: 'slider', | |||
| hidden: ()=>material.blending !== CustomBlending || | |||
| material.blendSrc !== ConstantAlphaFactor && | |||
| material.blendSrc !== OneMinusConstantAlphaFactor && | |||
| material.blendDst !== ConstantAlphaFactor && | |||
| material.blendDst !== OneMinusConstantAlphaFactor, | |||
| bounds: [0, 1], | |||
| property: [material, 'blendAlpha'], | |||
| }, | |||
| material.alphaMap !== undefined ? { | |||
| type: 'image', | |||
| property: [material, 'alphaMap'], | |||
| @@ -246,7 +358,7 @@ export const iMaterialUI = { | |||
| { | |||
| type: 'checkbox', | |||
| label: 'Override Environment', | |||
| // property: [this.userData, 'separateEnvMapIntensity'], | |||
| // property: [material.userData, 'separateEnvMapIntensity'], | |||
| getValue: ()=>material.userData.separateEnvMapIntensity === true, | |||
| setValue: (v: boolean)=>{ | |||
| material.userData.separateEnvMapIntensity = v | |||
| @@ -362,7 +474,7 @@ export const iMaterialUI = { | |||
| children: [ | |||
| { | |||
| type: 'slider', | |||
| bounds: [-1, 1], | |||
| bounds: [-500, 500], | |||
| stepSize: 0.001, | |||
| property: [material, 'bumpScale'], | |||
| hidden: ()=>!material.bumpMap, | |||
| @@ -312,7 +312,9 @@ export class PhysicalMaterial<TE extends IMaterialEventMap = IMaterialEventMap> | |||
| specularColor: new Color(1, 1, 1), | |||
| specularColorMap: null, | |||
| anisotropy: 0, | |||
| anisotropyRotation: 0, | |||
| anisotropyMap: null, | |||
| } | |||
| static MaterialTemplate: IMaterialTemplate<PhysicalMaterial, Partial<typeof PhysicalMaterial.MaterialProperties>> = { | |||
| @@ -40,6 +40,8 @@ export const threeMaterialPropList = { | |||
| blendSrcAlpha: null, | |||
| blendDstAlpha: null, | |||
| blendEquationAlpha: null, | |||
| blendColor: '#000000', | |||
| blendAlpha: 0, | |||
| depthFunc: LessEqualDepth, | |||
| depthTest: true, | |||
| depthWrite: true, | |||
| @@ -71,8 +71,9 @@ vec2 dHdxy_fwd_cb() { | |||
| #ifndef USE_BUMPMAP | |||
| vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) { | |||
| vec3 vSigmaX = dFdx( surf_pos.xyz ); | |||
| vec3 vSigmaY = dFdy( surf_pos.xyz ); | |||
| // normalize is done to ensure that the bump map looks the same regardless of the texture's scale | |||
| vec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) ); | |||
| vec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) ); | |||
| vec3 vN = surf_norm; // normalized | |||
| vec3 R1 = cross( vSigmaY, vN ); | |||
| @@ -12,8 +12,9 @@ uniform vec3 flakeFallOffParams; // useFallOff, fallOffFactor | |||
| vec3 perturbNormalArb_nb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) { | |||
| vec3 vSigmaX = dFdx( surf_pos.xyz ); | |||
| vec3 vSigmaY = dFdy( surf_pos.xyz ); | |||
| // normalize is done to ensure that the bump map looks the same regardless of the texture's scale | |||
| vec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) ); | |||
| vec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) ); | |||
| vec3 vN = surf_norm; // normalized | |||
| vec3 R1 = cross( vSigmaY, vN ); | |||
| @@ -1,9 +1,7 @@ | |||
| import {IGeometry, IMaterial, IObject3D} from '../../core' | |||
| import {BufferAttribute, InstancedMesh, Matrix4, Quaternion, Vector3} from 'three' | |||
| import {BufferAttribute, InstancedMesh} from 'three' | |||
| // noinspection ES6PreferShortImport | |||
| import {copyObject3DUserData} from '../../utils/serialization' | |||
| import {GLTFWriter2} from '../../assetmanager' | |||
| import {GLTFExporterPlugin} from 'three/examples/jsm/exporters/GLTFExporter' | |||
| export function autoGPUInstanceMeshes(matOrGeom: IMaterial|IGeometry) { | |||
| if (!(<IMaterial>matOrGeom).isMaterial && !(<IGeometry>matOrGeom).isBufferGeometry) return | |||
| @@ -87,60 +85,61 @@ export function autoGPUInstanceMeshes(matOrGeom: IMaterial|IGeometry) { | |||
| } | |||
| } | |||
| export class GLTFMeshGpuInstancingExporter implements GLTFExporterPlugin { | |||
| name = 'EXT_mesh_gpu_instancing' | |||
| constructor(public writer: GLTFWriter2) { | |||
| } | |||
| writeNode(object: any, nodeDef: any): void { | |||
| if (!object.isInstancedMesh) return | |||
| const writer = this.writer | |||
| const mesh = object as InstancedMesh | |||
| // @ts-expect-error not in ts | |||
| let attributes: any = mesh.sourceTrs | |||
| if (!attributes) { | |||
| const translationAttr = new Float32Array(mesh.count * 3) | |||
| const rotationAttr = new Float32Array(mesh.count * 4) | |||
| const scaleAttr = new Float32Array(mesh.count * 3) | |||
| const matrix = new Matrix4() | |||
| const position = new Vector3() | |||
| const quaternion = new Quaternion() | |||
| const scale = new Vector3() | |||
| for (let i = 0; i < mesh.count; i++) { | |||
| mesh.getMatrixAt(i, matrix) | |||
| matrix.decompose(position, quaternion, scale) | |||
| position.toArray(translationAttr, i * 3) | |||
| quaternion.toArray(rotationAttr, i * 4) | |||
| scale.toArray(scaleAttr, i * 3) | |||
| } | |||
| attributes = { | |||
| TRANSLATION: new BufferAttribute(translationAttr, 3), | |||
| ROTATION: new BufferAttribute(rotationAttr, 4), | |||
| SCALE: new BufferAttribute(scaleAttr, 3), | |||
| } | |||
| } | |||
| attributes = { | |||
| // @ts-expect-error todo add to ts | |||
| TRANSLATION: writer.processAccessor(attributes.TRANSLATION), | |||
| ROTATION: (writer as any).processAccessor(attributes.ROTATION), | |||
| SCALE: (writer as any).processAccessor(attributes.SCALE), | |||
| } | |||
| if (mesh.instanceColor) | |||
| attributes._COLOR_0 = (writer as any).processAccessor(mesh.instanceColor) | |||
| writer.extensionsUsed[ this.name ] = true | |||
| // @ts-expect-error todo add to ts | |||
| writer.extensionsRequired[ this.name ] = true | |||
| nodeDef.extensions = nodeDef.extensions || {} | |||
| nodeDef.extensions[ this.name ] = {attributes} | |||
| } | |||
| } | |||
| // added to three.js | |||
| // export class GLTFMeshGpuInstancingExporter implements GLTFExporterPlugin { | |||
| // name = 'EXT_mesh_gpu_instancing' | |||
| // constructor(public writer: GLTFWriter2) { | |||
| // } | |||
| // | |||
| // writeNode(object: any, nodeDef: any): void { | |||
| // if (!object.isInstancedMesh) return | |||
| // | |||
| // const writer = this.writer | |||
| // | |||
| // const mesh = object as InstancedMesh | |||
| // | |||
| // // @ts-expect-error not in ts | |||
| // let attributes: any = mesh.sourceTrs | |||
| // if (!attributes) { | |||
| // const translationAttr = new Float32Array(mesh.count * 3) | |||
| // const rotationAttr = new Float32Array(mesh.count * 4) | |||
| // const scaleAttr = new Float32Array(mesh.count * 3) | |||
| // | |||
| // const matrix = new Matrix4() | |||
| // const position = new Vector3() | |||
| // const quaternion = new Quaternion() | |||
| // const scale = new Vector3() | |||
| // | |||
| // for (let i = 0; i < mesh.count; i++) { | |||
| // mesh.getMatrixAt(i, matrix) | |||
| // matrix.decompose(position, quaternion, scale) | |||
| // | |||
| // position.toArray(translationAttr, i * 3) | |||
| // quaternion.toArray(rotationAttr, i * 4) | |||
| // scale.toArray(scaleAttr, i * 3) | |||
| // } | |||
| // attributes = { | |||
| // TRANSLATION: new BufferAttribute(translationAttr, 3), | |||
| // ROTATION: new BufferAttribute(rotationAttr, 4), | |||
| // SCALE: new BufferAttribute(scaleAttr, 3), | |||
| // } | |||
| // } | |||
| // | |||
| // attributes = { | |||
| // // @ts-expect-error todo add to ts | |||
| // TRANSLATION: writer.processAccessor(attributes.TRANSLATION), | |||
| // ROTATION: (writer as any).processAccessor(attributes.ROTATION), | |||
| // SCALE: (writer as any).processAccessor(attributes.SCALE), | |||
| // } | |||
| // | |||
| // if (mesh.instanceColor) | |||
| // attributes._COLOR_0 = (writer as any).processAccessor(mesh.instanceColor) | |||
| // | |||
| // writer.extensionsUsed[ this.name ] = true | |||
| // // @ts-expect-error todo add to ts | |||
| // writer.extensionsRequired[ this.name ] = true | |||
| // | |||
| // nodeDef.extensions = nodeDef.extensions || {} | |||
| // nodeDef.extensions[ this.name ] = {attributes} | |||
| // } | |||
| // } | |||